准备好BeanFactory,因为@Autowired需要在BeanFactory中找需要的Bean参数
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
beanFactory.registerSingleton("bean2",new Bean2());
beanFactory.registerSingleton("bean1",new Bean1());
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());//@Value
new 一个后处理器对象,设置其Bean工厂属性
AutowiredAnnotationBeanPostProcessor processor = new AutowiredAnnotationBeanPostProcessor();
processor.setBeanFactory(beanFactory);
首先自己new一个对象,没有经过后处理器处理,打印结果
Bean3 bean3 = new Bean3();
System.out.println(bean3);
可见属性还没有赋值
执行后处理器:
processor.postProcessProperties(null,bean3,"bean3");//执行依赖注入,解析@Autowirde @Value
System.out.println(bean3);
打印:
Bean3属性已经赋上值了
postProcessProperties()方法属于InstantiationAwareBeanPostProcessor接口定义的方法的,在之前自定义Bean处理器时使用过,可以在依赖注入的时候执行方法
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);
}
}
其中第一行执行findAutowiringMetadata()方法就是去分析Bean3类中,有哪些成员变量上有@Autowired和@Value 的信息,封装在返回结果metadata中
由于方法是私有的,利用反射更好的观察运行过程
Method findAutowiringMetadata = AutowiredAnnotationBeanPostProcessor.class.getDeclaredMethod("findAutowiringMetadata", String.class, Class.class, PropertyValues.class);
findAutowiringMetadata.setAccessible(true);
InjectionMetadata metadata = (InjectionMetadata) findAutowiringMetadata.invoke(processor, "bean3", bean3, null);
用debug查看 metadata
其中的InjectdElements封装着要注入的方法和属性
调用metadata的inject方法,实现注入属性
metadata.inject(bean3,"bean3",null);
加入${}解析器
beanFactory.addEmbeddedValueResolver(new StandardEnvironment()::resolvePlaceholders);//解析${}
打印:
如何根据类型找对象?
1.反射获取方法或变量
2.封装一个DependencyDescriptor对象
3.调用beanFactory.doResolveDependency()
//3.如何按类型找值
Field bean1 = Bean3.class.getDeclaredField("bean1");
//参数:1.传入要注入的字段 2.是否时必须的,false指找不到也不会报错
DependencyDescriptor dd1 = new DependencyDescriptor(bean1, false);
Object o = beanFactory.doResolveDependency(dd1, null, null, null);
System.out.println(o);
打印:
成功找到对象,之后可以通过反射设置其值
bean1.setAccessible(true);
bean1.set(bean3,o);
System.out.println(bean3);