《Spring設計思想》15-bean初始化中BeanPostProcessor的回調

上一節講到bean初始化方法initializeBean方法的第一步,invokeAwareMethods。

這節將初始化bean的第二步,applyBeanPostProcessorsBeforeInitialization方法

看代碼實現:

遍歷beanFactory裏面的beanPostProcessor,執行postProcessBeforeInitialization方法,


/**
 * factory的回調,允許用戶自定義bean
 * Factory hook that allows for custom modification of new bean instances,
 * e.g. checking for marker interfaces or wrapping them with proxies.
 * applicationContext 可以自己注入新的beanPostProcessor用來改造bean
 * <p>ApplicationContexts can autodetect BeanPostProcessor beans in their
 * bean definitions and apply them to any beans subsequently created.
 * Plain bean factories allow for programmatic registration of post-processors,
 * applying to all beans created through this factory.
 * 一般是在postProcessAfterInitiazation方法中使用代理包裝bean
 * <p>Typically, post-processors that populate beans via marker interfaces
 * or the like will implement {@link #postProcessBeforeInitialization},
 * while post-processors that wrap beans with proxies will normally
 * implement {@link #postProcessAfterInitialization}.

 */
public interface BeanPostProcessor {

	/**
	 * Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean
	 * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
	 * or a custom init-method). The bean will already be populated with property values.
	 * The returned bean instance may be a wrapper around the original.
	 * <p>The default implementation returns the given {@code bean} as-is.
	 *調用初始化前處理
	 */
	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

	/**
	 * Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean
	 * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
	 * or a custom init-method). The bean will already be populated with property values.
	 * The returned bean instance may be a wrapper around the original.
	 * <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean
	 * instance and the objects created by the FactoryBean (as of Spring 2.0). The
	 * post-processor can decide whether to apply to either the FactoryBean or created
	 * objects or both through corresponding {@code bean instanceof FactoryBean} checks.
	 * <p>This callback will also be invoked after a short-circuiting triggered by a
	 * {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method,
	 * in contrast to all other BeanPostProcessor callbacks.
	 * 調用初始化後處理
	 */
	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

看簡單的實現用例:

public class BeanInitializationDemo implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if(bean instanceof UserHolder){
            UserHolder userHolder = (UserHolder) bean;
            System.out.println("初始化前調用 PostProcessorBeforeInitialiation");
            userHolder.setDescript("我經歷過了postProcessBeforeInitialization");
        }
        return bean;
    }
}

注意:beanFactory的例子中只能手動添加BeanPostProcessor。

public class BeanLifyCycleDemo {
    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        // beanPostProcessor只能手動添加到beanFactory,不像applicationContext可以自己修改beanfactory的BeanPostProcessor
        beanFactory.addBeanPostProcessor(new BeanInitializationDemo());
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
        beanDefinitionReader.loadBeanDefinitions("META-INF/dependency-lookup-context.xml");
        beanFactory.addBeanPostProcessor(new BeanInstantiaitionAwareImpl());
        UserHolder userHolder =  (UserHolder)beanFactory.getBean("userHolder");
        System.out.println(userHolder);
    }
}

看輸出:

ApplicationContext的例子

public class BeanLifeCycleInApplicationContextDemo {

    public static void main(String[] args) {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("META-INF/dependency-lookup-context.xml");
        applicationContext.refresh();
        applicationContext.getBean(UserHolder.class);
        applicationContext.close();
    }
}

xml:

輸出:

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