这是beanFactory中常见的一些后处理器:
其中这俩个属于bean后处理器:
internalAutowiredAnnotationProcessor解析@Autowired、@Value
internalCommonAnnotationProcessor解析@Resource、@PostConstruct、@PreDestroy
Bean后处理器的作用:为Bean生命周期各个阶段提供扩展。
下面让我来演示一下bean后处理器的作用:
首先看一下基础代码:
public class a04Application {
public static void main(String[] args) {
//1
//GenericApplicationContext是一个干净的容器,”干净“指的是没有添加额外的beanFactory后处理器和bean后处理器
GenericApplicationContext context = new GenericApplicationContext();
//用原始方法注册三个bean
context.registerBean("bean1", Bean1.class);
context.registerBean("bean2", Bean2.class);
context.registerBean("bean3", Bean3.class);
//初始化容器
context.refresh(); //执行beanFactory后处理器,添加bean后处理器,初始化所有单例
//销毁容器
context.close();
}
}
//这里也可以用DefaultListableBeanFactory,但该容器在添加后处理器的时候需要一个个的手动的去加,并且开启。非常麻烦。而GenericApplicationContext有个refresh方法,能帮我们做这些事。
Bean1代码:
public class Bean1 {
private static final Logger log = LoggerFactory.getLogger(Bean1.class);
private Bean2 bean2;
@Autowired
public void setBean2(Bean2 bean2){
log.info("@Autowired生效:{}",bean2);
this.bean2=bean2;
}
private Bean3 bean3;
@Resource
public void setBean3(Bean3 bean3){
log.info("@Resource生效:{}",bean3);
this.bean3=bean3;
}
private String home;
@Autowired
public void setHome(@Value("${JAVA_HOME}")String home){
log.info("@Value生效:{}",home);
this.home=home;
}
@PostConstruct
public void init(){
log.info("@PostConstruct生效");
}
@PreDestroy
public void destroy(){
log.info("@PreDestroy生效");
}
@Override
public String toString() {
return "Bean1{" +
"bean2=" + bean2 +
", bean3=" + bean3 +
", home='" + home + '\'' +
'}';
}
}
在Bean1类中我们分别用@Autowired注入Bean2,@Resource注入Bean3,@Value注入环境变量中的端口号,@PostConstruct注入初始化,@PreDestroy注入销毁。
Bean2和Bean3中什么也没有:
public class Bean2 {
}
现在运行的话,结果只会显示把Bean1、2、3三个类注入到了spring容器中,但并没有运行Bean1类中的诸多bean注入。现在还不能解析有关Bean的注解。
下面我们添加internalAutowiredAnnotationProcessor解析@Autowired、@Value 的后处理器:
public class a04Application {
public static void main(String[] args) {
//1
//GenericApplicationContext是一个干净的容器,”干净“指的是没有添加额外的beanFactory后处理器和bean后处理器
GenericApplicationContext context = new GenericApplicationContext();
//用原始方法注册三个bean
context.registerBean("bean1", Bean1.class);
context.registerBean("bean2", Bean2.class);
context.registerBean("bean3", Bean3.class);
//2
context.registerBean(AutowiredAnnotationBeanPostProcessor.class);//解析@Autowired @Value注解的后处理器
//初始化容器
context.refresh(); //执行beanFactory后处理器,添加bean后处理器,初始化所有单例
//销毁容器
context.close();
}
}
此时运行会报错:No qualifying bean of type 'java.lang.String' available
因为在用@Value注解值注入时,还会用到另一个类去获取变量的真正的值,但默认的解析器没有该功能。
设置新的注解解析器,帮我们获取值
public class a04Application {
public static void main(String[] args) {
//1
//GenericApplicationContext是一个干净的容器,”干净“指的是没有添加额外的beanFactory后处理器和bean后处理器
GenericApplicationContext context = new GenericApplicationContext();
//用原始方法注册三个bean
context.registerBean("bean1", Bean1.class);
context.registerBean("bean2", Bean2.class);
context.registerBean("bean3", Bean3.class);
//3 设置一个新的注解解析器的实现 ,帮助我们获取变量的值
context.getDefaultListableBeanFactory()
.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
//2
context.registerBean(AutowiredAnnotationBeanPostProcessor.class);//解析@Autowired @Value注解的后处理器
//初始化容器
context.refresh(); //执行beanFactory后处理器,添加bean后处理器,初始化所有单例
//销毁容器
context.close();
}
}
结果:
已经显示@Value和@Autowired生效了
但@Resource注解的Bean3还没注入,我们继续添加后处理器:
public class a04Application {
public static void main(String[] args) {
//1
//GenericApplicationContext是一个干净的容器,”干净“指的是没有添加额外的beanFactory后处理器和bean后处理器
GenericApplicationContext context = new GenericApplicationContext();
//用原始方法注册三个bean
context.registerBean("bean1", Bean1.class);
context.registerBean("bean2", Bean2.class);
context.registerBean("bean3", Bean3.class);
//3 设置一个新的注解解析器的实现 ,帮助我们获取变量的值
context.getDefaultListableBeanFactory()
.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
//2
context.registerBean(AutowiredAnnotationBeanPostProcessor.class);//解析@Autowired @Value注解的后处理器
//4 @Resource、初始化、销毁等注解还不能解析
context.registerBean(CommonAnnotationBeanPostProcessor.class);//解析@Resource,@PostConstruct,@PreDestroy注解
//初始化容器
context.refresh(); //执行beanFactory后处理器,添加bean后处理器,初始化所有单例
//销毁容器
context.close();
}
}
结果:
可以看到@Resource、@PostConstruct、@PreDestroy都生效了。
实际开发中我们还可能遇到这样的需要:用@ConfigurationProperties注解根据前缀和类中的属性名称去匹配配置环境中的信息,比如:javax.home java.version属性读取出来赋值给类中的属性。
我们先来准备一个bean,然后把环境变量注入:
@Component
@ConfigurationProperties(prefix = "java")
public class Bean4 {
private String home;
private String version;
public String getHome(){
return home;
}
public void setHome(String home){
this.home=home;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
@Override
public String toString() {
return "Bean4{" +
"home='" + home + '\'' +
", version='" + version + '\'' +
'}';
}
}
其中的home和version变量分别为jdk的路径和版本号。
我们现在把Bean4注入到容器中,尝试获取环境变量:
public class a04Application {
public static void main(String[] args) {
//1
//GenericApplicationContext是一个干净的容器,”干净“指的是没有添加额外的beanFactory后处理器和bean后处理器
GenericApplicationContext context = new GenericApplicationContext();
//用原始方法注册三个bean
context.registerBean("bean1", Bean1.class);
context.registerBean("bean2", Bean2.class);
context.registerBean("bean3", Bean3.class);
//5
context.registerBean("bean4", Bean4.class);
//3 设置一个新的注解解析器的实现 ,帮助我们获取变量的值
context.getDefaultListableBeanFactory()
.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
//2
context.registerBean(AutowiredAnnotationBeanPostProcessor.class);//解析@Autowired @Value注解的后处理器
//4 @Resource、初始化、销毁等注解还不能解析
context.registerBean(CommonAnnotationBeanPostProcessor.class);//解析@Resource,@PostConstruct,@PreDestroy注解
//5
System.out.println(context.getBean(Bean4.class));
//初始化容器
context.refresh(); //执行beanFactory后处理器,添加bean后处理器,初始化所有单例
//销毁容器
context.close();
}
}
结果:
home和value值都是null,因为我们需要再加载一个bean后处理器:解析@ConfigurationProperties注解的bean后处理器
public class a04Application {
public static void main(String[] args) {
//1
//GenericApplicationContext是一个干净的容器,”干净“指的是没有添加额外的beanFactory后处理器和bean后处理器
GenericApplicationContext context = new GenericApplicationContext();
//用原始方法注册三个bean
context.registerBean("bean1", Bean1.class);
context.registerBean("bean2", Bean2.class);
context.registerBean("bean3", Bean3.class);
//5
context.registerBean("bean4", Bean4.class);
//3 设置一个新的注解解析器的实现 ,帮助我们获取变量的值
context.getDefaultListableBeanFactory()
.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
//2
context.registerBean(AutowiredAnnotationBeanPostProcessor.class);//解析@Autowired @Value注解的后处理器
//4 @Resource、初始化、销毁等注解还不能解析
context.registerBean(CommonAnnotationBeanPostProcessor.class);//解析@Resource,@PostConstruct,@PreDestroy注解
//6.解析@ConfigurationProperties注解的bean后处理器
ConfigurationPropertiesBindingPostProcessor.register(context.getDefaultListableBeanFactory());
//5
System.out.println(context.getBean(Bean4.class));
//初始化容器
context.refresh(); //执行beanFactory后处理器,添加bean后处理器,初始化所有单例
//销毁容器
context.close();
}
}
再次运行:
可以看到已经获取到了环境变量。