Spring源碼擴展篇-BeanFactoryPostProcessor

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);
    }
}

上面是實現了把某個類型的標識和具體的實例進行了映射.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章