spring有以下特点:
1、非侵入式:基于spring开发的应用不依赖于spring的API,即使更换框架也可以继续使用
2、控制反转:IOC是指将对象的创建权交给Spring去创建,在spring之前对象的创建都是由我们自己在代码中new得,而spring之后都是由框架创建。
3、依赖注入:DI是指依赖的对象不需要手动的setXXX方法,而是通过配置赋值
4、容器:spring是一个容器,它包含并且管理应用对象的生命周期
所有的类都会在spring容器中登记,告诉spring自己是什么,需要什么,然后会在系统运行到适当的时候把你所需的东西主动给你,同时也把你交给其他类。所有类的创建销毁都有spring来控制,也就是说控制对象生存周期的不再是引用它的对象,而是spring
IOC
在没有spring之前,当你需要一杯橙汁时,你需要自己创造,此时你需要杯子、糖、橙子等,但这是在有了spring之后你仅仅需要把自己的要求提给spring,这时你并没有自己动手创造,但是却得到了一杯橙汁
package pojo; public class Source { private String fruit; // 类型 private String sugar; // 糖分描述 private String size; // 大小杯 /* setter and getter */ }
在src目录下配置applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean name="source" class="pojo.Source"> <property name="fruit" value="橙子"/> <property name="sugar" value="多糖"/> <property name="size" value="超大杯"/> </bean> </beans>
package test; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import pojo.Source; public class TestSpring { @Test public void test(){ ApplicationContext context = new ClassPathXmlApplicationContext( new String[]{"applicationContext.xml"} ); Source source = (Source) context.getBean("source"); System.out.println(source.getFruit()); System.out.println(source.getSugar()); System.out.println(source.getSize()); } }
关于IOC我们学校的课本上有一段很棒的陈述:
在一个系统中,可以将所有的类分为两种,调用类和被调用类,在软件设计方法和设计模式中,一共出现了3种不同的类间调用的模式:自己创建、工厂模式和外部注入,其中外部注入就是IOC,
可以看出来,第一种方法用了JavaBean类中的setter方法,对测试类中实例化对象并赋值,
可以看出来,第二种方法依赖于工厂创建,测试类所需的对象由工厂创建。
而第三种则不需要自己创建对象,而对于对象属性的赋值也是由xml文件完成,降低了耦合性,而且在修改xml文件之后不需要重新修改和编译具体的Java代码,提高了灵活性。
spring通过大量引入Java的反射机制,动态生成Bean对象并注入到程序中避免了硬编码,实现该功能的是BeanFactory,而ApplicationContext继承了BeanFactory接口
Spring通过ApplicationContext或BeanFactory接口来实现对容器的加载,ApplicationContext的实现类如下:
1、ClassPathXmlApplicationContext:从CLASSPATH下加载配置文件
2、FileSystemXmlApplicationContext:从系统中加载配置文件
ApplicationContext ctx=new ClassPathXmlApplicationContext("bean.xml");或
ApplicationContext ctx=new FileSystemXmlApplicationContext("classpath:bean.xml");
然后获取bean实例 Moveable animal =(Moveable) ctx.getBean("animal");
当然ApplicationContext 还可以使用声明的方式来创建,一般是在启动web服务器的同时自动加载spring的容器功能,方法是在web.xml中配置监听器ContextLoaderListener,
DI
依赖注入的3种方式:
1、接口注入
2、setter注入
3、构造方法注入
下面通过setter注入演示一下
是指spring创建对象的过程中,将对象依赖属性通过配置设置给该对象
package pojo; public class JuiceMaker { // 唯一关联了一个 Source 对象 private Source source = null; /* setter and getter */ public String makeJuice(){ String juice = "xxx用户点了一杯" + source.getFruit() + source.getSugar() + source.getSize(); return juice; } }
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean name="source" class="pojo.Source"> <property name="fruit" value="橙子"/> <property name="sugar" value="多糖"/> <property name="size" value="超大杯"/> </bean> <bean name="juickMaker" class="pojo.JuiceMaker"> <property name="source" ref="source" /> </bean> </beans>
package test; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import pojo.JuiceMaker; import pojo.Source; public class TestSpring { @Test public void test(){ ApplicationContext context = new ClassPathXmlApplicationContext( new String[]{"applicationContext.xml"} ); Source source = (Source) context.getBean("source"); System.out.println(source.getFruit()); System.out.println(source.getSugar()); System.out.println(source.getSize()); JuiceMaker juiceMaker = (JuiceMaker) context.getBean("juickMaker"); System.out.println(juiceMaker.makeJuice()); } }
下面演示构造器注入:
Animal.java public class Animal{ private String animalType; private String moveMode; public Animal(String animalType,String moveMode){ this.animalType=animalType; this.moveMode=moveMode; } public void move{ String move Message=animalType+"can" +moveMode; system.out.println(moveMessage); } }
<bean id="animal" cladd="constructor.Animal"> <constructor-arg index="0" type ="java.lang.String" value="Bird"> <constructor-arg index="1" type ="java.lang.String" value="fly"> </bean>
每个<constructor-arg>指定构造函数的一个参数,index表示指定参数的顺序,即指定的是构造方法的第几个参数,type指定类型,value指明参数的值
假设没有依赖注入功能,我们一般会通过下面几步完成
1、读取标注或者配置文件,看看juiceMaker依赖的是那个Source,拿到类名
2、使用反射API,基于雷鸣实例化对应的对象实例
3、通过实例的getter和setter方法传递给JuiceMaker
其实spring也是这么做的。就是工厂的生产方式
AOP
面向切面编程是spring的一个强大功能,AOP可以将程序的业务代码和系统服务代码(如事务管理、日志记录等)分离开,在业务逻辑完全不知道的情况下为其提供系统服务。这样业务逻辑只需要负责和业务处理有关的操作,不用关心系统服务的问题,通过AOP可以实现业务和非业务的分离。AOP可以关注系统的“截面”,在适当的时候“拦截”程序的执行流程,吧程序的预处理和后处理交给某个拦截器来完成。
Jionpoint----------------------------------------------指那些被拦截到的点,在spring中,可以被动态代理拦截目标类的方法
Pointcut-----------------------------------------------指要对哪些Joinpoint进行拦截,即被拦截的连接点
Advice-------------------------------------------------值拦截到Joinpoint之后要做的事情,即对切入点增强的内容
Target-------------------------------------------------指代理的目标对象
Weaving----------------------------------------------指把增强代码应用到目标上,生成对象代理的过程
proxy--------------------------------------------------指生成的代理对象
Aspect------------------------------------------------切入点和通知的结合
关注点(concern)所关注的与业务无关的公共服务,如日志、授权认证等就是一个关注点,表示要做什么
连接点(Joinpoint)是指在程序执行过程中某个特定的点,通常这些点需要添加关注点的公共。表示“在哪里做”
切面(Aspect)将各个业务对象之中的关注点收集起来,设计成独立、可重用、职责清晰的对象,就是一个类,而关注点是其中的一个方法
通知(advice)指切面在程序运行到某个连接点是所触发的动作,在这个动作中可以自定义处理逻辑,一个切面可以包括多个通知,切面的真正逻辑就是通过编写通知来提供与业务逻辑无关的系统服务,许多AOP框架都是以拦截器作为通知模型,通知表示“具体怎么做”
目标对象(Target)就是指一个通知被应用的对象或目标,也称被通知的对象
织入(weaving)是把切面连接点目标对象的过程,这个过程可以在编译期完成,也可以在类加载和运行时完成
切入点(Pointcut)是匹配连接点的断言,当切面横切目标对象时,会产生许多交叉点,这点都由切入点表达式来决定
部分借鉴https://www.cnblogs.com/wmyskxz/p/8820371.html
https://blog.csdn.net/zangdaiyang1991/article/details/90788013