ioc中的annotation配置
※ @Autowired
1)、Spring 通过一个 BeanPostProcessor 对 @Autowired 进行解析,所以要让 @Autowired 起作用必须事先在 Spring 容器中声明 AutowiredAnnotationBeanPostProcessor Bean。
<!-- 该 BeanPostProcessor 将自动起作用,对标注 @Autowired 的 Bean 进行自动注入 -->
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
或者使用下面的隐式注册(隐式注册 post-processors 包括了
AutowiredAnnotationBeanPostProcessor,CommonAnnotationBeanPostProcessor,PersistenceAnnotationBeanPostProcessor,RequiredAnnotationBeanPostProcessor。)
<?xml version="1.0" encoding="UTF-8"?>
<context:annotation-config/>
</beans>
2)、@Autowired默认按照类型匹配的方式进行注入
3)、@Autowired注解可以用于成员变量、setter方法、构造器函数等
4)、使用@Autowired注解先按照byTYpe查找,如果找到多个,则按照byName的形式查找,否则报错
5)、Spring 允许我们通过 @Qualifier 注释指定注入 Bean 的名称。@Autowired 和 @Qualifier 结合使用时,自动注入的策略变成 byName 了。
public class MovieRecommender {
@Autowired
@Qualifier("mainCatalog")
private MovieCatalog movieCatalog;
private CustomerPreferenceDao customerPreferenceDao;
@Autowired
public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}
例:
实体类:
package com.briup.bean;
public class SrcBean {
private long id;
@Override
public String toString() {
return "SrcBean [id=" + id + "]";
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
}
package com.briup.bean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
public class DestBean {
/*
* 注解写在全局变量上是直接赋值
* 打破类的私有性
*/
@Autowired
@Qualifier("src")
private /*@Qualifier("src1")*/SrcBean src;
public DestBean() {
super();
}
@Autowired(required=true)
public DestBean(@Qualifier("src1")SrcBean src) {
this.src = src;
}
@Override
public String toString() {
return "DestBean [src=" + src + "]";
}
public SrcBean getSrc() {
return src;
}
/*
* @Autowired自动装配
* 先基于类型找,如果找到多个
* 在基于名字查找(基于名字查找
* 是基于参数的变量名字查找)
*
* 出现的位置
* 1.set方法
* 2.全局变量
* 3.构造器
* @Autowired(required=false)
* required为true表示必须的,基于类型
* 或者名字一定要找到对象,找不多报错
* required为flase,找到装配,找不到忽略
* @Qualifier 声明名字,基于名字找到
* 位置
* 不能写在构造器之上,构造器中参数
* 参数声明之前可以写
*
* 注意:set方法和构造器和全局变量都写注解
* set方法生效
* 构造器和全局变量都注解了,
* 全局变量生效
*/
//@Autowired
// @Qualifier("src1")
public void setSrc(/*@Qualifier("src1")*/SrcBean src1) {
this.src = src1;
}
}
配置文件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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
">
<!-- 告诉spring检查单前配置bean标签
中所有class对应的类是否有
@Autowired
注解
-->
<!-- <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor">
</bean> -->
<!-- 让spring检查class中对应的各种注解
@Autowired AutowiredAnnotationBeanPostProcessor,
@Resource @PostConstruct @PreDestory CommonAnnotationBeanPostProcessor,
PersistenceAnnotationBeanPostProcessor,
@Required RequiredAnnotationBeanPostProcessor
-->
<context:annotation-config></context:annotation-config>
<bean name="dest"
class="com.briup.bean.DestBean" >
</bean>
<bean name="src"
class="com.briup.bean.SrcBean">
<property name="id" value="100"></property>
</bean>
<bean name="src1"
class="com.briup.bean.SrcBean">
<property name="id" value="101"></property>
</bean>
</beans>
测试代码:
@Test
public void annotation_test(){
try {
ClassPathXmlApplicationContext cp=
new ClassPathXmlApplicationContext(
"com/briup/IOC/annotation.xml");
System.out.println(cp.getBean("dest"));
} catch (Exception e) {
e.printStackTrace();
}
}
※ @Resource
1)、@Resource 的作用相当于 @Autowired,只不过 @Autowired 按 byType 自动注入,
@Resource 默认按 先用byName,如果找不到合适的就再用byType来注入.
2)、要让 JSR-250(@Resource属于这种注解 ) 的注释生效,除了在 Bean 类中标注这些注释外,
还需要在 Spring 容器中注册一个负责处理这些注释的 BeanPostProcessor
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/>
3)、@Resource 有两个属性是比较重要的,分别是 name 和 type,Spring 将 @Resource 注释的 name 属性解析为 Bean 的名字,而 type 属性则解析为 Bean 的类型。所以如果使用 name 属性,则使用 byName 的自动注入策略,而使用 type 属性时则使用 byType 自动注入策略。如果既不指定 name 也不指定 type 属性,这时将通过反射机制使用 byName 自动注入策略。
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Resource
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
}
※ @PostConstruct 和 @PreDestroy
标注了 @PostConstruct 注释的方法将在类实例化后调用,而标注了 @PreDestroy 的方法将在类销毁之前调用。
public class CachingMovieLister {
@PostConstruct
public void populateMovieCache() {
// populates the movie cache upon initialization...
}
@PreDestroy
public void clearMovieCache() {
// clears the movie cache upon destruction...
}
}
※ @Component
1)、使用@Component注解可以直接定义Bean,而无需在xml定义。但是若两种定义同时存在,xml中的定义会覆盖类中注解的Bean定义。
2)、@Component 有一个可选的入参,用于指定 Bean 的名称。
@Component
public class ActionMovieCatalog implements MovieCatalog {
// ...
}
3)、<context:component-scan/> 允许定义过滤器将基包下的某些类纳入或排除。Spring 支持以下 4 种类型的过滤方式:
(不要求)
过滤器类型 表达式范例
annotation org.example.SomeAnnotation
assignable org.example.SomeClass
regex org\.example\.Default.*
aspectj org.example..*Service+
下面这个XML配置会忽略所有的@Repository注解
<beans ...>
<context:component-scan base-package="org.example">
<context:include-filter type="regex" expression=".*Stub.*Repository"/>
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
</context:component-scan>
</beans>
4)、默认情况下通过 @Component 定义的 Bean 都是 singleton 的,如果需要使用其它作用范围的 Bean,可以通过 @Scope 注释来达到目标,其默认作用域是"singleton",如果要换成其他作用区域,直接后面添加类型即可比如 @Scope("prototype") ,spring2.0后 又增加了request ,session和global session 4个作用区域
@Scope("prototype")
@Component
public class MovieFinderImpl implements MovieFinder {
// ...
}
5)、Spring 2.5以后引入了更多典型化注解(stereotype annotations): @Component、@Service和 @Controller。 @Component是所有受Spring管理组件的通用形式; 而@Repository、@Service和 @Controller则是@Component的细化, 用来表示更具体的用例(例如,分别对应了持久化层、服务层和表现层)
@Service
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Autowired
public SimpleMovieLister(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
}
@Repository
public class JpaMovieFinder implements MovieFinder {
// implementation elided for clarity
}
6)、要检测这些类并注册相应的bean,需要在XML中包含以下元素,其中'basePackage'是两个类的公共父包 (或者可以用逗号分隔的列表来分别指定包含各个类的包)。
<?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-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<context:component-scan base-package="org.example"/>
</beans>
此外,在使用组件扫描元素时,AutowiredAnnotationBeanPostProcessor 和CommonAnnotationBeanPostProcessor会隐式地被包括进来。 也就是说,连个组件都会被自动检测并织入 - 所有这一切都不需要在XML中提供任何bean配置元数据。
例:
实体类:
package com.briup.bean;
import javax.annotation.PreDestroy;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
//@Component
@Repository("src")
public class SrcBean {
/*
* 基本数据类型或者字符串
* set方法上赋值
* 全局变量
*/
// @Value("101");
//@Value(value="101")
private long id;
public SrcBean() {
}
public SrcBean(long id) {
this.id = id;
}
@Override
public String toString() {
return "SrcBean [id=" + id + "]";
}
public long getId() {
return id;
}
@Value("101")
public void setId(long id) {
this.id = id;
}
@PreDestroy
public void destory(){
System.out.println("destory...222.");
}
}
package com.briup.bean;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
/*
* @Component让spring构建单前对象
* 相当与在配置文件中配置了bean标签
* @Component("dest") 参数是给当前对象
* 起名字
* 默认名字类名,类名首字母大写
* 默认名字类名首字母小写
* 类名第一个第二个字母大写,
* 默认名字全类名
* @Scope("")两个
* singleton
* prototype 非单列
* request 每次请求构建一个对象
* session
* global session
* @Component细分,区分web项目
* 层次用的
* @Controller web层
* @Service 业务逻辑层service
* @Repository数据持久层dao
*/
//@Component("dest")
//@Scope("prototype")
//@Component(value="dest")
//@Controller("dest")
@Service("dest")
//@Repository
public class DestBean {
/*
* 注解写在全局变量上是直接赋值
* 打破类的私有性
*/
// @Autowired
// @Qualifier("src1")
@Resource
private /*@Qualifier("src1")*/SrcBean src;
/*
* 对象构建初始化的方法
*/
@PostConstruct
public void init_test(){
System.out.println("init....");
}
/*
* 对象销毁的时候的方法
* (本质从spring容器中移除的时候)
* 该方法的执行保证当前对象是单列
*/
@PreDestroy
public void destory(){
System.out.println("destory1111....");
}
public DestBean() {
super();
}
// @Autowired(required=true)
public DestBean(/*@Qualifier("src1")*/ SrcBean src) {
this.src = src;
}
@Override
public String toString() {
return "DestBean [src=" + src + "]";
}
public SrcBean getSrc() {
return src;
}
/*
* @Autowired自动装配
* 先基于类型找,如果找到多个
* 在基于名字查找(基于名字查找
* 是基于参数的变量名字查找)
*
* 出现的位置
* 1.set方法
* 2.全局变量
* 3.构造器
* @Autowired(required=false)
* required为true表示必须的,基于类型
* 或者名字一定要找到对象,找不多报错
* required为flase,找到装配,找不到忽略
* @Qualifier 声明名字,基于名字找到
* 位置
* 不能写在构造器之上,构造器中参数
* 参数声明之前可以写
*
* 注意:set方法和构造器和全局变量都写注解
* set方法生效
* 构造器和全局变量都注解了,
* 全局变量生效
* @Resource也是完成自动注入对象
* 默认是基于名字查找对象,名字
* 按照类型找,
* 位置:
* set方法上 名字是set方法去掉set
* 首字母小写
* @Resource(name="src")
* name属性基于名字查找,找不到
* 报错
* @Resource(type=SrcBean.class)
* 基于类型去找
* 注意:即声明type类型查找,同时
* set方法去掉set首字母小写的名字
* xml文件有bean对象,按名字查找
* @Resource(name="src",type=SrcBean.class)
* name属性和type属性并存的时候
* 基于名字开始找,名字如果找不到
* 直接报错
*/
// @Autowired()
// @Qualifier("src1")
// @Resource
// @Resource(name="src")
//@Resource(name="src",type=SrcBean.class)
public void setSrc3(/*@Qualifier("src1")*/SrcBean src3) {
this.src = src3;
}
}
配置文件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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
">
<!-- 告诉spring检查单前配置bean标签
中所有class对应的类是否有
@Autowired
注解
-->
<!-- <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor">
</bean> -->
<!-- 让spring检查class中对应的各种注解
@Autowired AutowiredAnnotationBeanPostProcessor,
@Resource @PostConstruct @PreDestory CommonAnnotationBeanPostProcessor,
PersistenceAnnotationBeanPostProcessor,
@Required RequiredAnnotationBeanPostProcessor
-->
<!-- <context:annotation-config></context:annotation-config> -->
<!-- 扫描含有注解的类
base-package指向含有注解类的包
如果多个包有注解,逗号隔开-->
<context:component-scan
base-package="com.briup.bean,com.briup.pojo">
<!-- 扫描包含哪些注解,一般不写 -->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
<!-- 忽略注解
type 属性是annotation
expression注解的全限定名
type属性是assignable
扫描类的全限定名
type属性是regex 正则表达式
type属性是aspectj aspectj语句
-->
<!-- <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/> -->
<context:exclude-filter type="assignable"
expression="com.briup.bean.SrcBean"/>
</context:component-scan>
<!-- <bean name="dest"
class="com.briup.bean.DestBean" >
</bean>
<bean name="src"
class="com.briup.bean.SrcBean">
<property name="id" value="100"></property>
</bean>
<bean name="src1"
class="com.briup.bean.SrcBean">
<property name="id" value="101"></property>
</bean> -->
</beans>
测试代码:
@Test
public void annotation_test(){
try {
ClassPathXmlApplicationContext cp=
new ClassPathXmlApplicationContext(
"com/briup/IOC/annotation.xml");
DestBean db=
(DestBean) cp.getBean("dest");
System.out.println(db);
cp.destroy();
} catch (Exception e) {
e.printStackTrace();
}
}