2.spring源码-BeanPostProcessor后置处理之ApplicationContextAwareProcessor,实现spring容器中某一个类的bean对象在初始化时需要得到Spring容器内容。

需求:我们的需求是,在spring初始化完毕时,使我们自定义一个类Bird类可以得到spring容器内容。

实现步骤:

1.首先我们来看一下ApplicationContextAwareProcessor这个类,它是BeanPostProcessor(后置处理器)的一个实现类。所以ApplicationContextAwareProcessor里面也必定有后置处理器接口的两个前置和后置方法。

我们来看一下ApplicationContextAwareProcessor的前置方法:由前面讲解的后置处理器(链接:https://www.cnblogs.com/WNof11020520/p/10598745.html)可知,所有bean对象初始化前都会执行BeanPostProcessor接口实现类的前置方法postProcessBeforeInitialization,所以所有bean对象初始化前都会执行ApplicationContextAwareProcessor的postProcessBeforeInitialization方法。

 1 @Nullable
 2     public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
 3         AccessControlContext acc = null;
 4         if(System.getSecurityManager() != null && (bean instanceof EnvironmentAware || 
 5                                                     bean instanceof EmbeddedValueResolverAware || 
 6                                                     bean instanceof ResourceLoaderAware || 
 7                                                     bean instanceof ApplicationEventPublisherAware || 
 8                                                     bean instanceof MessageSourceAware || 
 9                                                     bean instanceof ApplicationContextAware)) {
10             acc = this.applicationContext.getBeanFactory().getAccessControlContext();
11         }
12 
13         if(acc != null) {
14             AccessController.doPrivileged(() -> {
15                 this.invokeAwareInterfaces(bean);
16                 return null;
17             }, acc);
18         } else {
19             this.invokeAwareInterfaces(bean);
20         }
21 
22         return bean;
23     }
24 
25     private void invokeAwareInterfaces(Object bean) {
26         if(bean instanceof Aware) {
27             if(bean instanceof EnvironmentAware) {
28                 ((EnvironmentAware)bean).setEnvironment(this.applicationContext.getEnvironment());
29             }
30 
31             if(bean instanceof EmbeddedValueResolverAware) {
32                 ((EmbeddedValueResolverAware)bean).setEmbeddedValueResolver(this.embeddedValueResolver);
33             }
34 
35             if(bean instanceof ResourceLoaderAware) {
36                 ((ResourceLoaderAware)bean).setResourceLoader(this.applicationContext);
37             }
38 
39             if(bean instanceof ApplicationEventPublisherAware) {
40                 ((ApplicationEventPublisherAware)bean).setApplicationEventPublisher(this.applicationContext);
41             }
42 
43             if(bean instanceof MessageSourceAware) {
44                 ((MessageSourceAware)bean).setMessageSource(this.applicationContext);
45             }
46 
47             if(bean instanceof ApplicationContextAware) {
48                 ((ApplicationContextAware)bean).setApplicationContext(this.applicationContext);
49             }
50         }
51 
52     }

2.看以上代码第9、15、19、48行可知,假若bean对象的类是ApplicationContextAware类型的话,就会调用invokeAwareInterfaces方法,然后执行第48行,将spring容器赋值给bean对象的applicationContext属性。

所以重要的实现思路来了:

  a.Bird类实现ApplicationContextAware接口,并添加一个ApplicationContext类型的属性context,并实现ApplicationContextAware接口的方法:

 1 @Component
 2 public class Bird implements ApplicationContextAware {
 3     //得到管理它的Spring容器
 4     private ApplicationContext context;
 5 
 6     @Override
 7     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
 8         this.context = applicationContext;
 9     }
10 
11     @Override
12     public String toString() {
13         return "Bird [context=" + context + "]";
14     }
15 }

  b.写一个测试类,测试结果:

 1 public class TestMain {
 2 
 3     public static void main(String[] args) {
 4         // 1.获得Spring容器对象
 5         AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig.class);
 6         System.out.println("Spring容器 " + context);
 7         Bird bird = (Bird) context.getBean("bird");
 8         System.out.println(bird);
 9     }
10 }

  c.查看测试输出的结果:输出结果显示,TestMain 类的main方法中new出来的context和Bird组件的bean对象的context属性地址相同,所以Bird的bean对象得到了spring容器内容。

1 "C:\Program Files\Java\jdk1.8.0_25\bin\java" -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:52099,suspend=y,server=n -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_25\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_25\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_25\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_25\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_25\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_25\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_25\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_25\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_25\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_25\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_25\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_25\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_25\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_25\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_25\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_25\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_25\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_25\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_25\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_25\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_25\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_25\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar;D:\kaikeba_java\2018-11-28-spring-beanpostprocessor\02-项目\11_Spring_BeanPostProcessor的实现类介绍\target\test-classes;D:\kaikeba_java\2018-11-28-spring-beanpostprocessor\02-项目\11_Spring_BeanPostProcessor的实现类介绍\target\classes;D:\caowenlong\javaDevelopTool\apache-maven-3.5.3-bin\repo\org\springframework\spring-context\5.0.5.RELEASE\spring-context-5.0.5.RELEASE.jar;D:\caowenlong\javaDevelopTool\apache-maven-3.5.3-bin\repo\org\springframework\spring-aop\5.0.5.RELEASE\spring-aop-5.0.5.RELEASE.jar;D:\caowenlong\javaDevelopTool\apache-maven-3.5.3-bin\repo\org\springframework\spring-beans\5.0.5.RELEASE\spring-beans-5.0.5.RELEASE.jar;D:\caowenlong\javaDevelopTool\apache-maven-3.5.3-bin\repo\org\springframework\spring-core\5.0.5.RELEASE\spring-core-5.0.5.RELEASE.jar;D:\caowenlong\javaDevelopTool\apache-maven-3.5.3-bin\repo\org\springframework\spring-jcl\5.0.5.RELEASE\spring-jcl-5.0.5.RELEASE.jar;D:\caowenlong\javaDevelopTool\apache-maven-3.5.3-bin\repo\org\springframework\spring-expression\5.0.5.RELEASE\spring-expression-5.0.5.RELEASE.jar;D:\caowenlong\javaDevelopTool\IntelliJ IDEA 2016.2\lib\idea_rt.jar" com.kkb.test.TestMain
2 Connected to the target VM, address: '127.0.0.1:52099', transport: 'socket'
3 三月 26, 2019 11:26:26 上午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
4 信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@2ed94a8b: startup date [Tue Mar 26 11:26:26 CST 2019]; root of context hierarchy
5 Spring容器 org.springframework.context.annotation.AnnotationConfigApplicationContext@2ed94a8b: startup date [Tue Mar 26 11:26:26 CST 2019]; root of context hierarchy
6 Bird [context=org.springframework.context.annotation.AnnotationConfigApplicationContext@2ed94a8b: startup date [Tue Mar 26 11:26:26 CST 2019]; root of context hierarchy]
7 Disconnected from the target VM, address: '127.0.0.1:52099', transport: 'socket'
8 
9 Process finished with exit code 0

猜你喜欢

转载自www.cnblogs.com/WNof11020520/p/10599073.html