Spring IOC笔记
1、概念:
Ioc:控制反转即IoC (Inversion of Control),它把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理。所谓的“控制反转”概念就是对组件对象控制权的转移,从程序代码本身转移到了外部容器。
DI:依赖注入(Dependency Injection):组件不做定位查询,只提供普通的Java方法让容器去决定依赖关系。依赖注入是时下最流行的Io实现方式,注入方式分这三种:
a).接口注入(Interface Injection),
b).设值注入(Setter Injection),
c).构造器注入(Constructor Injection)。
<?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-2.5.xsd"> <bean id="u" class="com.bjsxt.dao.impl.UserDAOImpl"> <!-- 构造器注入 --> <!-- ①index索引指定对应传参 --> <constructor-arg index="0" value="jdbc:oracle:thin:@hostip:1521:dbname" /> <constructor-arg index="1" value="true" /> <!-- ②name参数名称指定对应传参 --> <!-- <constructor-arg name="url" value="jdbc:oracle:thin:@hostip:1521:dbname" />--> <!-- <constructor-arg name="show_Log" value="true" />--> <!-- ③type类型名称指定对应传参 --> <!-- <constructor-arg type="0" value="jdbc:oracle:thin:@hostip:1521:dbname" />--> <!-- <constructor-arg type="1" value="true" />--> </bean> <bean id="userService" class="com.bjsxt.service.UserService"> <!-- setter注入 --> <property name="userDao" ref="u" /> </bean> </beans>
2、id和name的区别:定义一个bean的时候,可以用id也可以用name,比如:
<bean id="userService" class="com.bjsxt.service.UserService"> <property name="userDao" ref="u" /> </bean> <bean name="userService" class="com.bjsxt.service.UserService"> <property name="userDao" ref="u" /> </bean>
两者是等效的,区别在于name里面可以含特殊字符而id不行。
3、简单属性的注入:很少用,一般在定义数据库驱动、url、用户名、密码的时候可以用简单属性注入的方式注入这些常量。
4、bean的作用域(生存范围):
a).singleton : 默认值,单例,表示容器初始化完了之后,每次getbean()拿到的都是同一个对象。
b).prototype : 原型,每次拿到的都是按照原型重行构造出来的新对象。
c).其它:request/session/global/application
5、集合注入
<bean id="moreComplexObject" class="example.ComplexObject"> <!-- results in a setAdminEmails(java.util.Properties) call --> <property name="adminEmails"> <props> <prop key="administrator">administrator@example.org</prop> <prop key="support">support@example.org</prop> <prop key="development">development@example.org</prop> </props> </property> <!-- results in a setSomeList(java.util.List) call --> <property name="someList"> <list> <value>a list element followed by a reference</value> <ref bean="myDataSource" /> </list> </property> <!-- results in a setSomeMap(java.util.Map) call --> <property name="someMap"> <map> <entry key="an entry" value="just some string"/> <entry key ="a ref" value-ref="myDataSource"/> </map> </property> <!-- results in a setSomeSet(java.util.Set) call --> <property name="someSet"> <set> <value>just some string</value> <ref bean="myDataSource" /> </set> </property> </bean>
6、自动装配:在<bean>中配置autowire属性,通常属性值会用到"byName"和"byType",配置之后,spring容器会根据类中属性名称或者类型自动将指定的bean注入到类中。
<bean name="userDao" class="com.bjsxt.dao.impl.UserDAOImpl"> <property name="daoId" value="1"></property> </bean> <bean id="userService" class="com.bjsxt.service.UserService" scope="prototype" autowire="byName"> </bean>
如上例,UserService类中如果有名称为userDao的属性,那么UserDAOImpl类将被自动注入到UserService类中。
也可以在<beans>标签中配置default-autowire属性,统一为所有的bean指定自动装配的方式。
7、懒加载(lazy-init):在<bean>中添加lazy-init="true",那么在容器启动的时候,不会初始化这个类,直到在程序中getBean()获取这个类的时候才初始化;同样也可以在<beans>中添加default-lazy-init="true",这样所有的bean统一被设置成了懒加载。这个功能大多数情况都用不到,但是在系统启动非常慢的情况下可以考虑加此功能。
<?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-2.5.xsd" default-lazy-init="true"> <bean name="userDao" class="com.bjsxt.dao.impl.UserDAOImpl"> <property name="daoId" value="1"></property> </bean> <bean id="userService" class="com.bjsxt.service.UserService" lazy-init="true" autowire="byType"> </bean> </beans>
8、bean的生命周期(lifecycle):
在<bean>中配置init-method属性指定bean初始化之后调用的方法,如:init-method="init";也可以实现InitializingBean接口,重写其afterPropertiesSet()方法。同样的,
在<bean>中配置destroy-method属性指定bean销毁之前调用的方法,如:destroy-method="destroy";也可以实现DisposableBean接口,重写其destroy()方法,需要注意的是不要和scope="prototype"一起使用,否则容器不负责各个bean的销毁,即调用容器(AbstractApplicationContext)的close()方法无效。
可以在<beans>中配置default-init-method和default-destroy-method属性为所有bean统一指定初始化之后及销毁之前调用的方法。
初始化及销毁方法的重写可用于日志功能,指定销毁的方法,可在其中关闭数据库连接等等。
<bean id="u" class="com.bjsxt.dao.impl.UserDAOImpl"> <constructor-arg index="0" value="jdbc:oracle:thin:@hostip:1521:dbname" /> <constructor-arg index="1" value="true" /> </bean> <bean id="userService" class="com.bjsxt.service.UserService" init-method="initMethod" destroy-method="destroyMethod"> <property name="userDao" ref="u" /> </bean>
package com.panda.service; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import com.panda.dao.UserDAO; import com.panda.model.User; public class UserService implements InitializingBean,DisposableBean{ private UserDAO userDao; public void initMethod() { System.out.println("属性destroy-init的方式init"); } public void add(User u){ this.userDao.save(u); } public UserDAO getUserDao() { return userDao; } public void setUserDao(UserDAO userDao) { this.userDao = userDao; } public UserService(){} public UserService(UserDAO userDao) { super(); this.userDao = userDao; } public void destroyMethod(){ System.out.println("属性destroy-method的方式destroy"); } //实现InitializingBean接口方法 public void afterPropertiesSet() throws Exception { System.out.println("实现InitializingBean接口的方式init"); } //实现DisposableBean接口方法 public void destroy() throws Exception { System.out.println("实现DisposableBean接口的方式destory"); } }
9、注解(Annotation)
在配置文件中添加<context:annotation-config/>,容器初始化之后,检查有此配置的话,会去实例化注解相关的 AutowiredAnnotationBeanPostProcessor
, CommonAnnotationBeanPostProcessor
,
PersistenceAnnotationBeanPostProcessor和
RequiredAnnotationBeanPostProcessor四个类,
为类里面的注解提供支持、处理。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:annotation-config></context:annotation-config> <bean id="u1" class="com.bjsxt.dao.impl.UserDAOImpl"> <property name="id" value="1"></property> </bean> <bean id="u2" class="com.bjsxt.dao.impl.UserDAOImpl"> <property name="id" value="2"></property> </bean> <bean id="userService" class="com.bjsxt.service.UserService"> </bean> </beans>
a).@Autowired:自动装配注解。默认是byType注入,当有多个同类型的bean时,使用@Qualifier("")进行区分(也可以在<bean>中配置<qualifier value="first"></qualifier>来区分同类型的不同bean,然后注解则可以写成@Qualifier("first"))。注解可以加在setter上(用@Autowired注解时方法名不一定是setter形式),也可以加在成员变量上。
package com.panda.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import com.panda.dao.UserDAO; import com.panda.model.User; public class UserService{ private UserDAO userDao; public void add(User u){ this.userDao.save(u); } public UserDAO getUserDao() { return userDao; } @Autowired public void setUserDao(@Qualifier("u1")UserDAO userDao) { this.userDao = userDao; } }
b).@Resource,作用与@Autowired一样。默认按name查找,找不到按type查找。
c).@Component,需要在配置文件中加入<context:component-scan base-package="com.panda"/>,将此注解加在类头部,即将类初始化为组件放在容器中作为一个bean存在,然后在代码中方法上面使用@Resource即可注入。
@Repository
, @Service
, @Controller注解也都有此功能。
d).@Scope,与bean中配置scope属性的作用一直。如scope="prototype"与@Scope("prototype").
e).@PostConstrut和@PreDestroy,作用等同于在bena中配置的init-method和init-destroy,配置在方法上,指定bean初始化之后和销毁之前的方法。