Spring详解之一:ICP(控制反转)
2016-05-29 00:00
330 查看
摘要: Spring是一个开源的控制反转(Inversion of Control-IOC)和面向切面(AOP)的容器框架,其主要作用是简化企业开发
#Spring
##Spring中的Bean的生命周期过程
通过Bean对应的Java类的构造器或者工厂方法创建Bean实例
为Bean的属性设置值和对其他Bean的引用(如Spring的xml文件中该Bean配置有properties子节点)
将Bean实例传递给Bean后置处理器(实现BeanPostProcessor接口的类,并在Spring的xml文件中配置如下Bean标签)的postProcessBeforeInitialization()方法操作
调用Bean的初始化方法(init-method)
将Bean实例传递给Bean后置处理器(实现BeanPostProcessor接口的类)的postProcessAfterInitialization()方法操作
使用Bean实例
当Spring容器关闭时,调用Bean的销毁方法(destroy-method)
###定义
Spring是一个开源的控制反转(Inversion of Control-IOC)和面向切面(AOP)的容器框架
其主要作用是简化企业开发
###控制反转IOC
定义:控制反转IOC指应用本身(PersonServiceBean)不负责依赖对象(PersonDao)的创建及维护,依赖的对象的创建及维护由外部容器负责,这样对依赖对象的控制权就由应用本身转移到了外部容器,这种控制权的转移就是所谓的反转。
在上面的例子中,PersonDao是在应用内部创建及维护的,故不是控制反转。若使用控制反转的话,则上面的例子需要进行修改。
###依赖注入(Dependency Injection-DI)
定义:在运行期,由外部容器动态的将依赖对象注入到组件中
对上述的代码进行控制反转下的修改,改为由外部容器负责创建:
通过setter方法进行依赖注入
通过构造器进行依赖注入
说明:
1、constructor-arg代表指定的构造器函数中的一个参数
2、可以利用index(参数的位置索引,从0开始),type(参数类型),ref(参数为依赖bean对象时,赋值为对应的bean标签的id),value(参数为基本数据类型时,可直接赋值)来指定唯一的构造器
3、如果一个bean的配置中没有constructor-arg属性,则必须利用默认的构造函数创建对象
4、所以在写一个javabean的时候,应该提供属性的setter方法,默认的构造器,带参数的构造器
使用Field注入(用于注解方式)
###Spring注入依赖对象的装配方式
手工装配(推荐使用)—— 存在两种编程方式
在xml配置文件中,通过在bean节点下配置,如上面展示的前2中注入方式
在Java代码中使用@Autowired或者@Resource注解的方式进行装配,但是我们需要在Spring的xml配置文件中添加如下配置:
#####自动装配(容易出现不可预知的错误)
实现方式:在需要注入依赖对象的应用,在Spring的xml文件中对应bean标签中定义autowire属性
autowire属性的值:
byType——按类型装配,在容器中寻找该类型匹配的bean,如果找到多个则抛出异常,如果没有找到即属性值为null
byName——按名称装配,在容器中寻找该名称匹配的bean,如果没有找到即属性值为null
constructor——与byType类似,不同之处在于它应用于构造器参数,如果构造器参数中没有找到与构造器参数类型一致的bean则抛出异常
autodetect——通过bean类的自省机制(introspection)来决定是使用constructor还是byType方式进行自行装配。如果发现默认的构造器,那就使用byType方式进行自行装配
#####手动装配:@Autowired和@Resource注解比较
@Autowired默认按照类型装配
可用于类的属性字段上,也可用于属性字段的setter方法上
默认情况下要求依赖对象必须存在,如果要允许依赖对象可以为null值时,可设置required属性为false
如果想让@Autowired按名称来装配的话,可以结合@Qualifier注解一起使用,如:
@Resource默认按名称装配,当找不到与名称匹配的bean时,会按类型装配
也可用于类的属性字段上,也可用于属性字段的setter方法上
默认按名称装配,同时名称可以通过其本身的属性name指定,如果没有指定的话:
@Resource默认按名称装配,当找不到与名称匹配的bean时,会按类型装配,但是如果指定了name属性,就只能按名称装配了。
###Spring的意义
通过控制反转降低组件之间的耦合度,实现软件各层之间的解耦;
可以使用容器提供的众多服务,如:事务管理服务、消息服务等等;
容器提供单利模式支持,开发人员不再需要自己编写实例代码;
容器提供AOP技术,利用它可以很容易实现如权限拦截、运行期监控等功能;
容器提供的众多辅助类,使用这些类能够加快应用的开发,如:JdbcTemplate、HibernateTemple;
对主流的应用框架提供了集成支持,如:集成了Hibernate、JPA、Sturts等,便于应用的开发。
###Spring实例化对象的方法
通过默认构造器的方法实例化:
在控制台将会打印”create Test”
由此可知:spring内部默认是调用了Test个类的默认的构造函数创建对象
通过静态工厂实例化
通过实例工厂实例化
###Spring中Bean的实例化模式(或者叫:实例作用域Scope)
singleton(Spring默认)
在每个Spring IOC容器中一个bean定义只有一个实例对象,也就是单例模式
prototype
每次从IOC容器中获取的bean都是新的对象。
###Spring中的Bean的实例化时机(实例对象的创建时机)
默认:
在Spring容器启动的时候创建即创建了各个Bean的实例对象,也就是在执行如下代码时创建了各个Bean的实例对象:
调用context.getBean()方法时创建:
可以通过设置bean标签中的lazy-init属性设置为true,即表示该bean在context.getBean()方法被调用时才会被创建实例对象
如果想对所有的bean都应用延迟初始化,可以在Spring配置文件的根节点beans设置dafault-lazy-init="true"属性:
lazy-init属性有3个属性值:
Default——相当于false,在spring容器启动的时候创建对象
True——在context.getBean时创建对象
False——在spring容器启动的时候创建对象
###Spring中Bean的实例化模式(实例作用域Scope)与Spring中的Bean的实例化时机(实例创建时机)的结合说明:当scope为prototype时,始终在context.getBean()方法调用时时创建各bean实例对象
###Spring中Bean的初始化
可以在Test类中定义一个方法,用于Test实例对象创建后,对该实例对象进行数据的初始化操作
执行步骤如下:
Spring容器创建Test实例对象;
由Spring容器内部调用init初始化方法,也就是说先实例化,然后才会初始化;
###Spring中Bean的销毁
Spring中Bean的销毁时机
只有在Spring容器被关闭的时候,该容器中的各个Bean对象才会被销毁
也就是在之心context.close()方法时,该容器中的各个Bean对象才会被销毁
可以在Test类中定义一个方法,用于Test实例对象销毁前,对该实例对象中使用的部分资源进行关闭等操作
注意:
destory方法是在Spring容器关闭后,Test实例对象销毁前执行;
如果一个bean的配置的实例化模式为”prototype”,则Spring容器不负责销毁。
###让Spring自动扫描和管理Bean
在Spring的xml配置文件中配置如下:
要想Spring对扫描的各java类进行管理,需要在各java类中注解标识
@Service——业务层组件
@Controller——控制层组件
@Repository——数据访问组件,也就是Dao组件
@Component——泛指组件,当组件不好归类时,使用这个注解标识
@Scope("prototype")——设置bean的实例化模式为非单例,一般与上述各注释一并使用
@PostConstruct——注解数据初始化的方法(原本为EJT3的注解,Spring进行了支持)
@PreDestory——注解Bean销毁前的方法
#Spring
##Spring中的Bean的生命周期过程
通过Bean对应的Java类的构造器或者工厂方法创建Bean实例
为Bean的属性设置值和对其他Bean的引用(如Spring的xml文件中该Bean配置有properties子节点)
将Bean实例传递给Bean后置处理器(实现BeanPostProcessor接口的类,并在Spring的xml文件中配置如下Bean标签)的postProcessBeforeInitialization()方法操作
<!-- com.abinge.spring.beans.MyBeanPostProcessor为自定义的实BeanPostProcessor接口的类 --> <!-- 该bean不用配置id,因为其对Spring容器中的全部Bean对象都会起作用进行操作处理 --> <bean class="com.abinge.spring.beans.MyBeanPostProcessor"/>
调用Bean的初始化方法(init-method)
将Bean实例传递给Bean后置处理器(实现BeanPostProcessor接口的类)的postProcessAfterInitialization()方法操作
使用Bean实例
当Spring容器关闭时,调用Bean的销毁方法(destroy-method)
###定义
Spring是一个开源的控制反转(Inversion of Control-IOC)和面向切面(AOP)的容器框架
其主要作用是简化企业开发
###控制反转IOC
定义:控制反转IOC指应用本身(PersonServiceBean)不负责依赖对象(PersonDao)的创建及维护,依赖的对象的创建及维护由外部容器负责,这样对依赖对象的控制权就由应用本身转移到了外部容器,这种控制权的转移就是所谓的反转。
public class PersonServiceBean{ private PersonDao personDao = new PersonDao(); public void save(Person person){ personDao.save(person); } }
在上面的例子中,PersonDao是在应用内部创建及维护的,故不是控制反转。若使用控制反转的话,则上面的例子需要进行修改。
###依赖注入(Dependency Injection-DI)
定义:在运行期,由外部容器动态的将依赖对象注入到组件中
对上述的代码进行控制反转下的修改,改为由外部容器负责创建:
通过setter方法进行依赖注入
//定义一个PersonServiceBean类 public class PersonServiceBean{ private PersonDao personDao; public void setPersonDaoBean(PersonDao personDao){ this.personDao = personDao; } public void save(Person person){ personDao.save(person); } } //在Spring配置文件中定义bean: //1、 <bean id="person" class="com.abinge.springtest.Person"/> <bean id="personDao" class="com.abinge.springtest.PersonDao"/> <bean id="personServiceBean" class="com.abinge.springtest.PersonServiceBean"> <property name="personDao" ref="personDao"/> </bean> //2、使用内部bean,此时PersonDao不能被其他bean使用 <bean id="person" class="com.abinge.springtest.Person"/> <bean id="personServiceBean" class="com.abinge.springtest.PersonServiceBean"> <property name="personDao"/> <bean class="com.abinge.springtest.PersonDao"/> </property> </bean> //在客户端 ApplicationContext context = newClassPathXmlApplicationContext("applicationContext.xml"); PersonServiceBean personServiceBean = (Test)context.getBean("personServiceBean"); Person person = (Test)context.getBean("person"); personServiceBean.save(person);
通过构造器进行依赖注入
//定义一个PersonServiceBean类 public class PersonServiceBean{ private PersonDao personDao; public PersonServiceBean(PersonDao personDao){ this.personDao = personDao; } public void save(Person person){ personDao.save(person); } } //在Spring配置文件中定义bean: <bean id="person" class="com.abinge.springtest.Person"/> <bean id="personDao" class="com.abinge.springtest.PersonDao"/> <bean id="personServiceBean" class="com.abinge.springtest.PersonServiceBean"> <constructor-arg index="0" ref="personDao" type="personDao"/> </bean> //在客户端 ApplicationContext context = newClassPathXmlApplicationContext("applicationContext.xml"); PersonServiceBean personServiceBean = (Test)context.getBean("personServiceBean"); Person person = (Test)context.getBean("person"); personServiceBean.save(person);
说明:
1、constructor-arg代表指定的构造器函数中的一个参数
2、可以利用index(参数的位置索引,从0开始),type(参数类型),ref(参数为依赖bean对象时,赋值为对应的bean标签的id),value(参数为基本数据类型时,可直接赋值)来指定唯一的构造器
3、如果一个bean的配置中没有constructor-arg属性,则必须利用默认的构造函数创建对象
4、所以在写一个javabean的时候,应该提供属性的setter方法,默认的构造器,带参数的构造器
使用Field注入(用于注解方式)
###Spring注入依赖对象的装配方式
手工装配(推荐使用)—— 存在两种编程方式
在xml配置文件中,通过在bean节点下配置,如上面展示的前2中注入方式
在Java代码中使用@Autowired或者@Resource注解的方式进行装配,但是我们需要在Spring的xml配置文件中添加如下配置:
<beans ……> <context:annotation-config/> </beans>
#####自动装配(容易出现不可预知的错误)
实现方式:在需要注入依赖对象的应用,在Spring的xml文件中对应bean标签中定义autowire属性
//对PersonServiceBean中的PersonServiceDao属性会按照类型自动装配注入 <bean id="personServiceBea" class="com.abinge.PersonServiceBean" autowire="byType"/>
autowire属性的值:
byType——按类型装配,在容器中寻找该类型匹配的bean,如果找到多个则抛出异常,如果没有找到即属性值为null
byName——按名称装配,在容器中寻找该名称匹配的bean,如果没有找到即属性值为null
constructor——与byType类似,不同之处在于它应用于构造器参数,如果构造器参数中没有找到与构造器参数类型一致的bean则抛出异常
autodetect——通过bean类的自省机制(introspection)来决定是使用constructor还是byType方式进行自行装配。如果发现默认的构造器,那就使用byType方式进行自行装配
#####手动装配:@Autowired和@Resource注解比较
@Autowired默认按照类型装配
可用于类的属性字段上,也可用于属性字段的setter方法上
@Autowired(required=false) @Qualifier("personDao"); private PersonDao personDao;//注解在字段上 @Autowired public void setPersonDao(PersonDao personDao){//注解在属性字段的setter方法上 this.personDao = personDao; }
默认情况下要求依赖对象必须存在,如果要允许依赖对象可以为null值时,可设置required属性为false
如果想让@Autowired按名称来装配的话,可以结合@Qualifier注解一起使用,如:
@Autowired(required=false) @Qualifier("personDao"); private PersonDao personDao;
@Resource默认按名称装配,当找不到与名称匹配的bean时,会按类型装配
也可用于类的属性字段上,也可用于属性字段的setter方法上
默认按名称装配,同时名称可以通过其本身的属性name指定,如果没有指定的话:
1、当@Resource注解注在属性字段上时,默认取字段的名称作为匹配bean名称寻找依赖对象 2、当@Resource注解注在属性的setter方法上时,默认取属性的名称作为匹配bean名称寻找依赖对象
@Resource默认按名称装配,当找不到与名称匹配的bean时,会按类型装配,但是如果指定了name属性,就只能按名称装配了。
###Spring的意义
通过控制反转降低组件之间的耦合度,实现软件各层之间的解耦;
Controller ——> Service ——>Dao
可以使用容器提供的众多服务,如:事务管理服务、消息服务等等;
容器提供单利模式支持,开发人员不再需要自己编写实例代码;
容器提供AOP技术,利用它可以很容易实现如权限拦截、运行期监控等功能;
容器提供的众多辅助类,使用这些类能够加快应用的开发,如:JdbcTemplate、HibernateTemple;
对主流的应用框架提供了集成支持,如:集成了Hibernate、JPA、Sturts等,便于应用的开发。
###Spring实例化对象的方法
通过默认构造器的方法实例化:
//Test类的定义: public class Test{ public Test(){ System.out.println("create Test"); } } //在Spring配置文件中定义bean: <bean id="test" class="com.abinge.springtest.Test"/> //在客户端 ApplicationContext context = newClassPathXmlApplicationContext("applicationContext.xml"); Test test = (Test)context.getBean("test");
在控制台将会打印”create Test”
由此可知:spring内部默认是调用了Test个类的默认的构造函数创建对象
通过静态工厂实例化
//Test类的定义: public class Test{ public Test(){ System.out.println("create Test"); } } //Test工厂的定义,需要在该工厂中定义一个静态的创建Test实例的方法: public class TestFactory{ public static Test getInstance(){ return new Test(); } } //在Spring配置文件中定义TestFactory的bean,而不是Test类的bean: <!--<bean id="test" class="com.abinge.springtest.Test"/>--> <bean id="testFactory" class="com.abinge.springtest.TestFactory" factory-method="getInstance"/> //在客户端 ApplicationContext context = newClassPathXmlApplicationContext("applicationContext.xml"); Test test = (Test)context.getBean("testFactory");
通过实例工厂实例化
//Test类的定义: public class Test{ public Test(){ System.out.println("create Test"); } } //Test工厂的定义,需要在改工厂中定义非静态的创建Test实例的方法: public class TestFactory{ public Test getInstance(){ return new Test(); } } //在Spring配置文件中定义TestFactory的bean,用于让Spring创建该工厂对象,同时定义一个创建Test类的bean: <!--<bean id="test" class="com.abinge.springtest.Test"/>--> <bean id="testFactory" class="com.abinge.springtest.TestFactory" /> <bean id="test" factory-bean="testFactory" factory-method="getInstance"/> //在客户端 ApplicationContext context = newClassPathXmlApplicationContext("applicationContext.xml"); Test test = (Test)context.getBean("test");
###Spring中Bean的实例化模式(或者叫:实例作用域Scope)
singleton(Spring默认)
在每个Spring IOC容器中一个bean定义只有一个实例对象,也就是单例模式
prototype
每次从IOC容器中获取的bean都是新的对象。
###Spring中的Bean的实例化时机(实例对象的创建时机)
默认:
在Spring容器启动的时候创建即创建了各个Bean的实例对象,也就是在执行如下代码时创建了各个Bean的实例对象:
ApplicationContext context = newClassPathXmlApplicationContext("applicationContext.xml");
调用context.getBean()方法时创建:
可以通过设置bean标签中的lazy-init属性设置为true,即表示该bean在context.getBean()方法被调用时才会被创建实例对象
<bean id="test" class="com.abinge.springtest.Test" lazy-init="true"/>
如果想对所有的bean都应用延迟初始化,可以在Spring配置文件的根节点beans设置dafault-lazy-init="true"属性:
<beans default-lazy-init="true" ……>
lazy-init属性有3个属性值:
Default——相当于false,在spring容器启动的时候创建对象
True——在context.getBean时创建对象
False——在spring容器启动的时候创建对象
###Spring中Bean的实例化模式(实例作用域Scope)与Spring中的Bean的实例化时机(实例创建时机)的结合说明:当scope为prototype时,始终在context.getBean()方法调用时时创建各bean实例对象
###Spring中Bean的初始化
可以在Test类中定义一个方法,用于Test实例对象创建后,对该实例对象进行数据的初始化操作
//Test类的定义: public class Test{ public Test(){ System.out.println("create Test"); } public init(){ //……相应的数据初始化代码 System.out.println("init data"); } } //在Spring配置文件中定义bean的同时,通过init-mathod属性指定数据初始化方法以完成数据初始化: <bean id="test" class="com.abinge.springtest.Test" init-mathod="init"/> //在客户端 ApplicationContext context = newClassPathXmlApplicationContext("applicationContext.xml"); Test test = (Test)context.getBean("test");
执行步骤如下:
Spring容器创建Test实例对象;
由Spring容器内部调用init初始化方法,也就是说先实例化,然后才会初始化;
###Spring中Bean的销毁
Spring中Bean的销毁时机
只有在Spring容器被关闭的时候,该容器中的各个Bean对象才会被销毁
也就是在之心context.close()方法时,该容器中的各个Bean对象才会被销毁
可以在Test类中定义一个方法,用于Test实例对象销毁前,对该实例对象中使用的部分资源进行关闭等操作
//Test类的定义: public class Test{ public Test(){ System.out.println("create Test"); } public void init(){ //……相应的数据初始化代码 System.out.println("init data"); } public void destory(){ //……相应的数据资源的关闭等操作代码 System.out.println("destory data"); } } //在Spring配置文件中定义bean的同时,通过destory-mathod属性指定数据资源关闭方法以完成资源的关闭: <bean id="test" class="com.abinge.springtest.Test" init-mathod="init" destory-mathod="destory"/> //在客户端 ApplicationContext context = newClassPathXmlApplicationContext("applicationContext.xml"); Test test = (Test)context.getBean("test");
注意:
destory方法是在Spring容器关闭后,Test实例对象销毁前执行;
如果一个bean的配置的实例化模式为”prototype”,则Spring容器不负责销毁。
###让Spring自动扫描和管理Bean
在Spring的xml配置文件中配置如下:
<beans ……> <!--<context:annotation-config/>--> <!--1、base-package="com.abinge":这样配置,Spring会自动扫描com.abinge包下及其子包下的java类,将这些Java类按照注解全部加载到其自己的容器中作为Bean对象进行管理--> <context:component-san base-package="com.abinge"/> <!-- 2、resource-pattern="service/*.class":具体指定Spring扫描包的路径,表示扫描com.abinge包下的子包service下的所有class文件 也就是com.abinge.service包下的class文件 --> <context:component-san base-package="com.abinge" resource-pattern="service/*.class"/> <!-- 3.通过exclude-filter和include-filter指定具体扫描路径 --> <context:component-san base-package="com.abinge" use-default-filters="false"> <!-- context:exclude-filter:通过expression属性指定排除指定包下com.abinge.service中的不扫描--> <context:exclude-filter type="annotation" expression="com.abinge.service"/> <!-- context:include-filter:通过expression属性指定只扫描指定包下com.abinge.service中的class对象 但是需要在context:component-san标签中设置属性use-default-filters="false"--> <context:include-filter type="annotation" expression="com.abinge.service"/> </context:component-san> </beans>
要想Spring对扫描的各java类进行管理,需要在各java类中注解标识
@Service——业务层组件
@Controller——控制层组件
@Repository——数据访问组件,也就是Dao组件
@Component——泛指组件,当组件不好归类时,使用这个注解标识
@Scope("prototype")——设置bean的实例化模式为非单例,一般与上述各注释一并使用
@PostConstruct——注解数据初始化的方法(原本为EJT3的注解,Spring进行了支持)
@PreDestory——注解Bean销毁前的方法
相关文章推荐
- Spring详解之二:AOP(面向切面)
- Spring详解之三:配置事务管理
- Spring详解之四:SpringMVC整合Mybatis相关配置文件信息
- Java多线程实现的三种方式
- key terms of Java programing
- 关于java的左移与右移
- java设计模式——策略模式
- java设计模式——工厂模式
- Spring学习笔记1——基础知识
- Java开发中的23种设计模式详解
- Spring学习笔记2——高级特性
- spring mvc 的工作原理(1)概述
- SpringMVC视图解析器ViewResovlet问题
- Num51 boss---05(定区添加,hessian入门,spring发hessian,关顾)
- [javaEE] Servlet中Session的使用
- Struts2-OGNL
- java线程学习-thread的一些方法
- spring mvc中的登录拦截器java类中,重写的三个方法是什么意思()
- Spring MVC Ajax返回中文乱码
- Spring ProxyFactory