spring容器初始化時,從資源中讀取到bean的相關定義後,保存在beanFactory的成員變量中,在實例化bean的操作就是依據這些bean的定義來做的,而在實例化之前,spring允許我們通過自定義擴展來改變bean的定義,定義一旦變了,後面的實例也就變了,而beanFactory後置處理器,即BeanFactoryPostProcessor就是用來改變bean定義的;
這裏總結一下spring內部是怎麼使用和加載的,具體源碼就不展示了,比較複雜
1. ApplicationContext擴展類可以調用AbstractApplicationContext.addBeanFactoryPostProcessor方法,將自定義的BeanFactoryPostProcessor實現類保存到ApplicationContext中;
2. spring容器初始化時,上一步中被加入到ApplicationContext的bean會被優先調用其postProcessBeanFactory方法;
3. 自定義的BeanFactoryPostProcessor接口實現類,也會被找出來,然後調用其postProcessBeanFactory方法;
4. postProcessBeanFactory方法被調用時,beanFactory會被作爲參數傳入,自定義類中可以使用該參數來處理bean的定義,達到業務需求;
5. 此時的spring容器還沒有開始實例化bean,因此自定義的BeanFactoryPostProcessor實現類不要做與bean實例有關的操作,而是
下面可以簡單介紹一下實際項目中怎麼使用:
@Service("calculateService")
public class CalculateServiceImpl implements CalculateService {
private String desc = "desc from class";
public void setDesc(String desc) {
this.desc = desc;
}
@Override
public int add(int a, int b) {
return a + b;
}
@Override
public String getServiceDesc() {
return desc;
}
}
定義自定義的beanfactory後置處理器:
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
AbstractBeanDefinition abstractBeanDefinition = (AbstractBeanDefinition) beanFactory.getBeanDefinition("calculateService");
MutablePropertyValues pv = abstractBeanDefinition.getPropertyValues();
pv.addPropertyValue("desc", "i am changed from bean factory post processor");
abstractBeanDefinition.setScope(BeanDefinition.SCOPE_SINGLETON);
}
}
上述代碼的功能很簡單,找到名爲”calculateService”的bean的定義對象,通過調用addPropertyValue方法,將定義中的desc屬性值改爲”Desc is changed from bean factory post processor”,這樣等名爲”calculateService”的bean被實例化出來後,其成員變量desc的值就是”Desc is changed from bean factory post processor”;可以看一下效果,此時此刻bean還沒有被實例化
當然也可以像下面這樣頂一個bean:
@Component
public class CompletStrategyBeanPostProccessor implements BeanFactoryPostProcessor {
public final static String STRAREG_PACKAGE ="com.njdt.post.build.completion";
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
Map<String, Class> handlerMap = Maps.newHashMapWithExpectedSize(3);
ClassFileScaner.scan(STRAREG_PACKAGE, CompletStrategyHandler.class).forEach(clazz ->{
System.out.println(clazz);
String type = clazz.getAnnotation(CompletStrategyHandler.class).name();
handlerMap.put(type, clazz);
});
//
// Set<Class<?>> classSet = ClassFileScaner.scan(STRAREG_PACKAGE, CompletStrategyHandler.class);
// Iterator<Class<?>> aa = classSet.iterator();
// while (aa.hasNext()) {
// String type = aa.getClass().getAnnotation(CompletStrategyHandler.class).name();
// handlerMap.put(type, aa.getClass());
// }
CompletStrategyContext context = new CompletStrategyContext(handlerMap);
//註冊實例到spring容器中
configurableListableBeanFactory.registerSingleton(CompletStrategyContext.class.getName(),context);
}
}
上面是實現了把某個類型的標識和具體的實例進行了映射.