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);
}
}
上面是实现了把某个类型的标识和具体的实例进行了映射.