Reference:
http://www.ibm.com/developerworks/cn/java/j-lo-spring25-ioc/
http://www.ibm.com/developerworks/cn/java/j-lo-spring25-mvc/
http://www.ibm.com/developerworks/cn/opensource/os-cn-spring-iocannt/
http://www.ibm.com/developerworks/cn/java/
《精通 Spring 2.x—企业应用开发精解》陈雄华 ([email protected]), 技术总监, 宝宝淘网络科技有限公司
http://download.csdn.net/detail/zheng12tian/2584987
Appicable scene:
Spring with Annotation:
1) Bean 的依赖关系是固定的,(如 Service 使用了哪几个 DAO 类),这种配置信息不会在部署时发生调整。
2) 类是自己写的,可以在源码里面加入 Annotation.
Spring with XML:
1) 部署时需要修改的,放在xml里面修改后不需要编译源码,例如: 数据源、缓存池、持久层操作模板类、事务管理等内容的配置。
2) 引用第三方库,则无法修改源代码,例如:JdbcTemplate、SessionFactoryBean
Spring with 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-2.5.xsd"> <bean id="boss" class="com.baobaotao.Boss"> <property name="car" ref="car"/> <property name="office" ref="office" /> </bean> <bean id="office" class="com.baobaotao.Office"> <property name="officeNo" value="002"/> </bean> <bean id="car" class="com.baobaotao.Car" scope="singleton"> <property name="brand" value="Jaguar XJ"/> <property name="price" value="89"/> </bean> </beans>
注入属性 @Autowired
//标注在字段上 public class Boss { @Autowired private Car car; @Autowired private Office office; } //标注在方法上 public class Boss { private Car car; private Office office; @Autowired public void setCar(Car car) { this.car = car; } } //标注在构造函数上 public class Boss { private Car car; private Office office; @Autowired public Boss(Car car ,Office office){ this.car = car; this.office = office ; } }//beans.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-2.5.xsd"> <!-- Spring 通过一个 BeanPostProcessor 对 @Autowired 进行解析,所以要让 @Autowired 起作用必须事先在 Spring 容器中声明 AutowiredAnnotationBeanPostProcessor Bean。--> <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/> <!-- 移除 boss Bean 的属性注入配置的信息, 扫描 Autowired 标注,注入属性, 默认按类型匹配 --> <bean id="boss" class="com.baobaotao.Boss"/> <bean id="office" class="com.baobaotao.Office"> <property name="officeNo" value="001"/> </bean> <bean id="car" class="com.baobaotao.Car" scope="singleton"> <property name="brand" value="Bugatti"/> <property name="price" value="4200"/> </bean> </beans>
1) 当找不到一个匹配的 Bean 时,Spring 容器将抛出 BeanCreationException 异常,并指出必须至少拥有一个匹配的 Bean。可以使用 @Autowired(required = false)
2) 如果 Spring 容器中拥有多个候选 Bean,Spring 容器在启动时也会抛出 BeanCreationException 异常。
public class Boss { @Autowired private Car car; @Autowired @Qualifier("office") private Office office; } @Autowired public void setOffice(@Qualifier("office") Office office) { this.office = office; }
@Autowired 可以对成员变量、方法以及构造函数
@Qualifier 的标注对象是成员变量、方法入参、构造函数入参。
//自动注入的策略就从 byType 转变成 byName
@Resource 注入属性
@Autowired 是 Spring 提供的, 默认按 byType 自动注入
@Resource 是 JSR250 定义的, Spring 也支持,与 @Autowired 等效, (默认按 byName 自动注入)
让 @Resource 生效,需要加 <bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/>
public class Boss { // 自动注入类型为 Car 的 Bean @Resource private Car car; // 自动注入 bean 名称为 office 的 Bean @Resource(name = "office") private Office office; }
JSR 250
JSR250 定义了 @Resource, @PostConstruct 和 @PreDestroy
@PostConstruct / @PreDestroy 等效于 实现 InitializingBean/DisposableBean 接口进行初始化和销毁。也可以通过 <bean> 元素的 init-method/destroy-method 属性指定初始化之后 / 销毁之前调用的操作方法。
@PostConstruct 可以定义在多个初始化方法上。而接口或者 init-method 只能一个。
让 JSR250的 Annotations 生效, 需要在 xml 里面加 BeanPostProcessor:
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/>
public static void main(String[] args) {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(new String[] {"beans.xml"};);
Boss boss = (Boss) ctx.getBean("boss");
System.out.println(boss);
ctx.destroy();// 关闭 Spring 容器,以触发 Bean 销毁方法的执行
}
使用<context:annotation-config/> 简化配置
<context:annotationconfig/> 将隐式地向 Spring 容器注册 AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、PersistenceAnnotationBeanPostProcessor、RequiredAnnotationBeanPostProcessor。
//beans.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" 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-2.5.xsd"> <context:annotation-config/> <bean id="boss" class="com.baobaotao.Boss"/> <bean id="office" class="com.baobaotao.Office"> <property name="officeNo" value="001"/> </bean> <bean id="car" class="com.baobaotao.Car" scope="singleton"> <property name="brand" value=" 红旗 CA72"/> <property name="price" value="2000"/> </bean> </beans>
使用 @Component
通过 @Autowired 或 @Resource 在 Bean 类中使用自动注入功能,
但是 Bean 还是在 XML 文件中通过 <bean> 进行定义 —— 也就是说,在 XML 配置文件中定义 Bean,通过 @Autowired 或 @Resource 为 Bean 的成员变量、方法入参或构造函数入参提供自动注入的功能。
通过注释定义 Bean,从 XML 配置文件中完全移除 Bean 定义的配置: @Component
//默认实例化为 car,首字母小写,也可以指定名称。 @Component("myCar") @Component public class Car { … } @Component("boss") public class Boss { @Autowired private Car car; @Autowired private Office office; … }
//beans.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" 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-2.5.xsd"> <context:component-scan base-package="com.baobaotao"/> </beans>
Filter:
<context:component-scan base-package="com.baobaotao">
<context:include-filter type="regex" expression="com\.baobaotao\.service\..*"/>
<context:exclude-filter type="aspectj" expression="com.baobaotao.util..*"/>
</context:component-scan>
<context:component-scan/>
不但启用了对类包进行扫描以实施注释驱动 Bean 定义的功能,
同时还启用了注释驱动自动注入的功能(即还隐式地在内部注册了 AutowiredAnnotationBeanPostProcessor 和 CommonAnnotationBeanPostProcessor),
因此当使用 <context:component-scan/> 后,就可以将 <context:annotation-config/> 移除了。
Scope
默认情况下通过 @Component 定义的 Bean 都是 singleton 的,如果需要使用其它作用范围的 Bean,可以通过 @Scope 注释来达到目标
@Scope("prototype")
@Component("boss")
public class Boss {
…
}
采用具有特殊语义的注释
@Repository, @Service, @Controller, @Component 是等效的
但是从注释类的命名上,这 3 个注释分别和持久层、业务层和控制层(Web 层)相对应。
虽然目前这 3 个注释和 @Component 相比没有什么新意,但 Spring 将在以后的版本中为它们添加特殊的功能。
所以,如果 Web 应用程序采用了经典的三层分层结构的话,最好在持久层、业务层和控制层分别采用 @Repository, @Service 和 @Controller 对分层中的类进行注释,而用 @Component 对那些比较中立的类进行注释。