第四讲:Bean后处理器
目录
1.1 AutowiredAnnotationBeanPostProcessor的Bean后处理器
1.2 CommonAnnotationBeanPostProcessor
1.3 ConfigurationPropertiesBindingPostProcessor
2.postProcessProperties() 这个方法实际调用的源码
学习目标
1.Bean后处理器的作用:为Bean生命周期各个阶段提供扩展
2.常见的后处理器
一、常见的Bean后处理器
package com.itheima.a04;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor;
import org.springframework.context.annotation.CommonAnnotationBeanPostProcessor;
import org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver;
import org.springframework.context.support.GenericApplicationContext;
/*
bean 后处理器的作用
*/
public class A04 {
public static void main(String[] args) {
// ⬇️GenericApplicationContext 是一个【干净】的容器
//干净---并没有跟我们添加一些后处理器 GenericApplicationContext-未注册的容器
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();
/*
学到了什么
a. @Autowired 等注解的解析属于 bean 生命周期阶段(依赖注入, 初始化)的扩展功能
b. 这些扩展功能由 bean 后处理器来完成
*/
}
}
package com.itheima.a04;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
public class Bean1 {
private static final Logger log = LoggerFactory.getLogger(Bean1.class);
private Bean2 bean2;
@Autowired
public void setBean2(Bean2 bean2) {
log.debug("@Autowired 生效: {}", bean2);
this.bean2 = bean2;
}
@Autowired
private Bean3 bean3;
@Resource
public void setBean3(Bean3 bean3) {
log.debug("@Resource 生效: {}", bean3);
this.bean3 = bean3;
}
private String home;
@Autowired
public void setHome(@Value("${JAVA_HOME}") String home) {
log.debug("@Value 生效: {}", home);
this.home = home;
}
@PostConstruct
public void init() {
log.debug("@PostConstruct 生效");
}
@PreDestroy
public void destroy() {
log.debug("@PreDestroy 生效");
}
@Override
public String toString() {
return "Bean1{" +
"bean2=" + bean2 +
", bean3=" + bean3 +
", home='" + home + '\'' +
'}';
}
}
package com.itheima.a04;
public class Bean2 {
}
package com.itheima.a04;
public class Bean3 {
}
我们执行一下 看一下这些注解到底解析了没有
结果并没有打印bean1中的信息 说明注解还没有解析
1.1 AutowiredAnnotationBeanPostProcessor的Bean后处理器
加入这个代码后 发现出现异常,默认的这个自动装配注解的bean后处理器是不支持值的依赖注入的 因此我们需要设置一下
1.2 CommonAnnotationBeanPostProcessor
1.3 ConfigurationPropertiesBindingPostProcessor
总结
1. AutowiredAnnotationBeanPostProcessor 在依赖注入阶段解析@Autowired 和@value
2.CommonAnnotationBeanPostProcessor 在依赖注入阶段解析@Resource 在初始化前解析@PostConstruct 销毁前解析@preDestroy
3.ConfigurationPropertiesBindingPostProcessor 在初始化前解析 @ConfigurationProperties注解
二、@Autowired bean后处理器执行分析
2.1 准备工作
package com.itheima.a04;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.annotation.InjectionMetadata;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver;
import org.springframework.core.MethodParameter;
import org.springframework.core.env.StandardEnvironment;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
// AutowiredAnnotationBeanPostProcessor 运行分析
public class DigInAutowired {
public static void main(String[] args) throws Throwable {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// beanFactory.registerBeanDefinition(); //前面用的是这个 比较麻烦 添加bean我们用下面的方法
beanFactory.registerSingleton("bean2", new Bean2()); // 不会走创建过程,依赖注入,初始化
beanFactory.registerSingleton("bean3", new Bean3());
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); // @Value
// 1. 查找哪些属性、方法加了 @Autowired, 这称之为 InjectionMetadata
// 2. 调用 InjectionMetadata 来进行依赖注入, 注入时按类型查找值
// metadata.inject(bean1, "bean1", null);
// System.out.println(bean1);
// 3. 如何按类型查找值
}
}
为绑定bean后处理器前
绑定后
2.2依赖注入前方法的源码
我们先找到metadata
因为metadata没有重写toString()我们使用断点debug查看
可以看出来 metadata中封装的就是@Autowired 和@Value的成员变量和方法
调用 InjectionMetadata 来进行依赖注入, 注入时按类型查找值
这里我们发现home中的${}并没有解析 ---是因为我们创建的时候并没有创建一个${}的解析器
总结
processor.postProcessProperties() 这个方法实际调用的就是第一先找到metadata
然后进行inject注入
metadata.inject(bean1, "bean1", null); 是如何按照类型查找的呢
1 查找成员变量
Field bean3 = Bean1.class.getDeclaredField("bean3"); //DependencyDescriptor -- 依赖描述 通过成员变量的类型 找 DependencyDescriptor dd1=new DependencyDescriptor(bean3,false); Object o = beanFactory.doResolveDependency(dd1, null, null, null); System.out.println(o);2.方法(值传入)
Method setHome =Bean1.class.getDeclaredMethod("setHome", String.class); DependencyDescriptor dd3=new DependencyDescriptor(new MethodParameter(setHome,0),false); Object o3 = beanFactory.doResolveDependency (dd3,null,null,null); System.out.println(o3);
3.方法 (对象)
如果容器中没有bean2对象
方法中我们设置的是false 直接返回null
如果设置为true 就会抛异常
总结
1.讲解了bean的三个后处理器
1. AutowiredAnnotationBeanPostProcessor 在依赖注入阶段解析@Autowired 和@value
2.CommonAnnotationBeanPostProcessor 在依赖注入阶段解析@Resource 在初始化前解析@PostConstruct 销毁前解析@preDestroy
3.ConfigurationPropertiesBindingPostProcessor 在初始化前解析 @ConfigurationProperties注解
2.postProcessProperties() 这个方法实际调用的源码
1.processor.postProcessProperties() 这个方法实际调用的就是 第一先找到metadata 然后进行inject注入2.inject的按照类型查找的原理
成员变量的依赖注入
方法的依赖注入
方法的值注入