需求:我們的需求是,在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