003-Spring4 擴展分析BeanPostProcessor、BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor
一、依賴註入ApplicationContext
方法一、@Autowired
創建一個User,內部使用ApplicationContext
@Component public class User { @Autowired private ApplicationContext applicationContext; public void show() { System.out.println("User:"+applicationContext.getClass()); } }View Code
使用
public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.lhx.spring.kuozhan"); System.out.println(context.getBean("user")); // System.out.println(context.getBean("createUser")); User bean = (User) context.getBean("user"); bean.show(); context.close(); }View Code
方法二、實現ApplicationContextAware接口
@Component public class Book implements ApplicationContextAware{ private ApplicationContext ApplicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {View Codethis.ApplicationContext=applicationContext; } public void show() { System.out.println("book:"+ApplicationContext.getClass()); } }
1)內部原理
接口BeanPostProcessor,內部方法,每一個bean初始化都會被執行
bean初始化屬性完畢後,即依賴裝配完成之後,postProcessBeforeInitialization
bean初始化在屬性設置之後,Bean init之後觸發的,postProcessAfterInitialization
作用:回調,返回代理對象等
如在postProcessBeforeInitialization中返回其他代理對象。
構建一個默認實現【兩個方法不能返回null】
package com.lhx.spring.kuozhan; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.stereotype.Component; @Component public class EchoBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("--------------postProcessBeforeInitialization-------------" + "bean" + bean.getClass()); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("--------------postProcessBeforeInitialization-------------" + "bean" + bean.getClass()); return bean; } }View Code
2)示例
User類
@Component public class User { private ApplicationContext applicationContext; @Autowired public void setApplicationContext(ApplicationContext applicationContext) { this.applicationContext = applicationContext; } public void init() { System.out.println("User init"); } public void show() { System.out.println("User:" + applicationContext.getClass()); } }View Code
UserConfig類
@Configuration public class MyConfig { @Bean(initMethod = "init") public User createUser() { return new User(); } }View Code
調用
System.out.println(context.getBean("user"));
查看日誌
User Set屬性
--------------postProcessBeforeInitialization-------------beanclass com.lhx.spring.kuozhan.User
User init
--------------postProcessAfterInitialization-------------beanclass com.lhx.spring.kuozhan.User
3)自行實現ApplicationContextAware,這裏起名為SpringContextAware,邏輯參考ApplicationContextAwareProcessor
public interface SpringContextAware { public void setApplicationContext(ApplicationContext applicationContext); }View Code
編寫ContextBeanPostProcessor
package com.lhx.spring.kuozhan; import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; @Component public class ContextBeanPostProcessor implements BeanPostProcessor { @Autowired private ApplicationContext applicationContext; @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof SpringContextAware) { SpringContextAware sca = (SpringContextAware) bean; sca.setApplicationContext(applicationContext); } return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { // TODO Auto-generated method stub return bean; } }View Code
實際類使用
package com.lhx.spring.kuozhan; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; @Component public class Dog implements SpringContextAware { private ApplicationContext applicationContext; public void setApplicationContext(ApplicationContext applicationContext) { this.applicationContext = applicationContext; } public void show() { System.out.println("Dog:" + applicationContext.getClass()); } }View Code
使用:
context.getBean(Dog.class).show();
4)查看ApplicationContextAware內部實現:
AnnotationConfigApplicationContext→GenericApplicationContext→AbstractApplicationContext
找打refresh方法,prepareBeanFactory,
// Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
ApplicationContextAwareProcessor內部
class ApplicationContextAwareProcessor implements BeanPostProcessor
方法三、Spring 4.3 新特性,構造方法直接添加,有局限性,與構造方法直接相關
@Component public class Bank { private ApplicationContext applicationContext; //spring 4.3 提供,與構造方法調用有關 public Bank(ApplicationContext applicationContext) { this.applicationContext=applicationContext; } public void show() { System.out.println("book:"+applicationContext.getClass()); } }View Code
二、容器擴展
2.1、BeanFactoryPostProcessor
在beanFactory之後,BeanFactoryPostProcessor容器初始化之後,只初始化一次,先於所有容器以及BeanPostProcessor
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
示例代碼擴展2
源碼:
AnnotationConfigApplicationContext→GenericApplicationContext→AbstractApplicationContext
找打refresh方法
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh(); // Tell the subclass to refresh the internal bean factory. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. registerBeanPostProcessors(beanFactory); // Initialize message source for this context. initMessageSource(); // Initialize event multicaster for this context. initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. onRefresh(); // Check for listener beans and register them. registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } // Destroy already created singletons to avoid dangling resources. destroyBeans(); // Reset ‘active‘ flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; } finally { // Reset common introspection caches in Spring‘s core, since we // might not ever need metadata for singleton beans anymore... resetCommonCaches(); } } }View Code
2.2、BeanDefinitionRegistryPostProcessor
BeanFactoryPostProcessor的子類BeanDefinitionRegistryPostProcessor
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
註冊一個Bean到Spring容器中,類似標註了@Componment
示例
新建一個Person類
public class Person { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Person [name=" + name + "]"; } }View Code
MyBeanDefinitionRegistryPostProcessor實現
package com.lhx.spring.kuozhan2; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; import org.springframework.stereotype.Component; @Component public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { // TODO Auto-generated method stub } @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { for (int i = 0; i < 10; i++) { BeanDefinitionBuilder rootBeanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Person.class); rootBeanDefinition.addPropertyValue("name", "admin" + i); registry.registerBeanDefinition("person" + i, rootBeanDefinition.getBeanDefinition()); } } }View Code
使用
public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.lhx.spring.kuozhan2"); System.out.println(context.getBean("person1")); context.getBeansOfType(Person.class).values().forEach(System.out::println); context.close(); }
當然在使用
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.lhx.spring.kuozhan2");
使用context也可以註入
context.registerBeanDefinition(beanName, beanDefinition);
beanDefinition定義可以使用:BeanDefinitionBuilder rootBeanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Person.class);
代碼地址:https://github.com/bjlhx15/spring-boot.git
003-Spring4 擴展分析BeanPostProcessor、BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor