GenericApplicationContext
准备工作,先了解一下GenericApplicationContext作用,它简单来说相当于一个比较简单的容器实现。里面没有添加任何的后处理器。这样可以在后续根据需要手动添加进行逐一测试。该容器有一个refresh()方法,执行的时候,会执行beanFactory后处理器,添加bean后处理器,初始化所有的单例。
public class ApplicationDemo {
public static void main(String[] args) {
GenericApplicationContext context = new GenericApplicationContext();
context.registerBean("bean1",Bean1.class);
context.registerBean("bean2",Bean2.class);
context.registerBean("bean3",Bean3.class);
context.refresh();
for (String beanDefinitionName : context.getBeanDefinitionNames()) {
System.out.println(beanDefinitionName);
}
context.close();
}
}
public class Bean1 {
private Bean2 bean2;
@Autowired
private Bean3 bean3;
private String home;
@Autowired
private void setBean2(Bean2 bean2) {
System.out.println("Autowired:::::bean2注入");
this.bean2 = bean2;
}
@Resource
private void setBean3(Bean3 bean3) {
System.out.println("Resource:::::bean3注入");
this.bean3 = bean3;
}
@Autowired
private void setJavaHome(@Value("${JAVA_HOME}") String home) {
System.out.println("Autowired:::::home获取");
this.home = home;
}
@PostConstruct
private void a() {
System.out.println("PostConstruct方法");
}
@PreDestroy
private void b() {
System.out.println("PreDestroy方法");
}
@Override
public String toString() {
return "Bean1{" +
"bean2=" + bean2 +
", bean3=" + bean3 +
", home='" + home + ''' +
'}';
}
}
public class Bean2 {}
public class Bean3 {}
先准备以上代码,只有Bean1里面添加了各种注入以及初始化和销毁方法,启动容器。结果只解析到三个自定义bean,bean1里面所写的各种注入都没有执行。因为上面也说到了,我们选用的这个容器默认是没有任何的后处理器。根据之前章节对后处理器的认识知道,想要执行bean1内的注入。需要有能够处理bean的后处理器才能够解析里面所写的内容,我们就先添加相关的后处理器。
context.getDefaultListableBeanFactory()
.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
context.registerBean(AutowiredAnnotationBeanPostProcessor.class);
context.registerBean(CommonAnnotationBeanPostProcessor.class);
这里补充一点,就是上面第一行代码的内容,我们回看上面写的例子,Bean1里面有一个使用值注入的setJavaHome方法,但是这里容器默认不支持值注入,这里换一个其他的实现方式。后面添加的两个后处理器,第一个是用来解析@Autowired和@Value注解的后处理器。第二个在之前章节中提到过是用来解析@Resource注解的解析器,但它还是用来解析@PostConstruct和@PreDestroy的解析器,看着好像是两类不同的注解,但这些也只能先记着了,唉。
输出结果:
Resource:::::bean3注入
Autowired:::::home获取
Autowired:::::bean2注入
PostConstruct方法
bean1
bean2
bean3
PreDestroy方法
到这里,基本和之前提到的DefaultListableBeanFactory容器的操作差不多,只是这里的容器调用refresh()方法,不用再循环获取添加的后处理器并进行依次的调用。
AutowiredAnnotationBeanPostProcessor浅析
上面简单使用了一下该后处理器的作用。这里通过部分源码来分析一下解析的过程原理。回顾bean生命周期中InstantiationAwareBeanPostProcessor接口的postProcessProperties方法执行时机,是发生依赖注入的时候。那可以猜测,具体的逻辑就是在该方法中实现的,找出源码。
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
//找到所有添加@Autowired和@Value
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
//反射属性赋值
metadata.inject(bean, beanName, pvs);
}dfdfdfdffg
catch (BeanCreationException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
return pvs;
}
这一段就是AutowiredAnnotationBeanPostProcessor实现的该方法逻辑。先找到所有被注解@Autowired和@Value的属性并存放到InjectionMetadata对象中的一个集合。
private final Collection<InjectedElement> injectedElements;
至于如何找到,有兴趣可以进一步查看findAutowiringMetadata方法逻辑,这里先简单分析一下不对源码底层做深究。找到后,就是通过反射进行逐一的属性赋值。