spring04 Bean 后处理器
后处理器作用
1. @Autowired 等注解的解析属于 bean 生命周期阶段(依赖注入, 初始化)的扩展功能,这些扩展功能由 bean 后处理器来完成
2. 每个后处理器各自增强什么功能
* AutowiredAnnotationBeanPostProcessor 解析 @Autowired 与 @Value
* CommonAnnotationBeanPostProcessor 解析 @Resource、@PostConstruct、@PreDestroy
* ConfigurationPropertiesBindingPostProcessor 解析 @ConfigurationProperties 根据 setter 方法注入
3. 另外 ContextAnnotationAutowireCandidateResolver 负责获取 @Value 的值,解析 @Qualifier、泛型、@Lazy 等
GenericApplicationContext context
= new GenericApplicationContext(); //干净的容器,没有多余的 Bean、 BeanFactory 后处理器
//注册 Bean 到容器中
context.registerBean(S04Bean1.class);
context.registerBean(S04Bean2.class);
context.registerBean(S04Bean3.class);
context.registerBean(S04Bean4.class);
//添加 Bean 后处理器
context.getDefaultListableBeanFactory()
.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); //负责获取 @Value 的值,解析 @Qualifier、泛型、@Lazy 等
context.registerBean(AutowiredAnnotationBeanPostProcessor.class); //解析 @Autowired、@Value 注解
context.registerBean(CommonAnnotationBeanPostProcessor.class); //解析 @Resource、@PostConstruct、@PreDestroy
ConfigurationPropertiesBindingPostProcessor.register(context.getDefaultListableBeanFactory()); //解析 ConfigurationProperties
// 初始化
context.refresh(); //刷新容器,将容器中的 BeanFactory 后处理器执行,将 Bean 后处理器添加,初始化所有单例
System.out.println(context.getBean(S04Bean4.class));
//销毁
context.close();
@Autowired bean 后处理器运行分析
1. AutowiredAnnotationBeanPostProcessor.findAutowiringMetadata 用来获取某个 bean 上加了 @Value @Autowired 的成员变量,方法参数的信息,表示为 InjectionMetadata
//创建 基础的 BeanFactory
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
beanFactory.registerSingleton("S04Bean2",new S04Bean2());// 创建过程,依赖注入,初始化都不会做,因为是个成品的 Bean 了
beanFactory.registerSingleton("S04Bean3",new S04Bean3());
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); // 获取 @Value 值
beanFactory.addEmbeddedValueResolver(new StandardEnvironment()::resolvePlaceholders); // ${} 的解析器
//创建 AutowiredAnnotationBeanPostProcessor Bean 后处理器
AutowiredAnnotationBeanPostProcessor beanPostProcessor
= new AutowiredAnnotationBeanPostProcessor();
beanPostProcessor.setBeanFactory(beanFactory); // 因为 Bean 的注入需要到 BeanFactory 中按类型查找
S04Bean1 s04Bean1 = new S04Bean1();
System.out.println(s04Bean1);
beanPostProcessor.postProcessProperties
(null, s04Bean1, "s04Bean1"); // 执行依赖注入 @Autowired、@Value
System.out.println(s04Bean1);
postProcessorProperties 源码 底层调用 findAutowiringMetadata 方法得到 InjectionMetadata 对象调用 inject 方法完成依赖注入
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
InjectionMetadata metadata = this.findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
metadata.inject(bean, beanName, pvs);
return pvs;
} catch (BeanCreationException var6) {
throw var6;
} catch (Throwable var7) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", var7);
}
}
得到 InjectionMetadata
//1.查找哪些方法属性加了 @Autowired 注解,称为 InjectionMetadata
Method findAutowiringMetadata = AutowiredAnnotationBeanPostProcessor.class
.getDeclaredMethod("findAutowiringMetadata", String.class, Class.class, PropertyValues.class);
findAutowiringMetadata.setAccessible(true);
InjectionMetadata metadata = (InjectionMetadata) findAutowiringMetadata.invoke(beanPostProcessor,
"S04Bean1", S04Bean1.class, null);// 获取 S04Bean1 上加了 @Autowired、@Value 的成员变量,方法参数信息
System.out.println(metadata);
2. InjectionMetadata 可以完成依赖注入
//2.调用 InjectionMetadata 来进行依赖注入,注入时按类型查找
metadata.inject(s04Bean1,"S04Bean1",null);
System.out.println(s04Bean1);
3. InjectionMetadata 内部根据成员变量,方法参数封装为 DependencyDescriptor 类型
4. 有了 DependencyDescriptor,就可以利用 beanFactory.doResolveDependency 方法进行基于类型的查找
//3.injection 按类型查找值
//1.得到目标方法
Method getBean3 = S04Bean1.class.getDeclaredMethod("getBean3", S04Bean3.class);
//2.创建 DependencyDescriptor (依赖描述)
DependencyDescriptor dependencyDescriptor // 方法第 1 个参数, 非必须,容器中找不到也不会报错
= new DependencyDescriptor(new MethodParameter(getBean3,0),false);
//3.调用 BeanFactory ,根据成员类型查找
Object o = beanFactory.doResolveDependency(dependencyDescriptor, null, null, null);
System.out.println(o);
//得到目标属性
Field s04Bean2 = S04Bean1.class.getDeclaredField("s04Bean2");
DependencyDescriptor dependencyDescriptor2 = new DependencyDescriptor(s04Bean2, false);
Object o2 = beanFactory.doResolveDependency(dependencyDescriptor2, null, null, null);
System.out.println(o2);
//得到 @Value 注入的值
Method getJavaHome = S04Bean1.class.getDeclaredMethod("getJavaHome");
DependencyDescriptor dependencyDescriptor3
= new DependencyDescriptor(new MethodParameter(getJavaHome, 0), true);
Object o3 = beanFactory.doResolveDependency(dependencyDescriptor3, null, null, null);
System.out.println(o3);
注入 JAVA_HOME 报错,正在寻找原因