整理一些spring常見的擴展點

一、各種後處理器

1.1、BeanDefinition與BeanFactory擴展

1.1.1、BeanDefinitionRegistryPostProcessor接口

/**
 * Extension to the standard {@link BeanFactoryPostProcessor} SPI, allowing for
 * the registration of further bean definitions <i>before</i> regular
 * BeanFactoryPostProcessor detection kicks in. In particular,
 * BeanDefinitionRegistryPostProcessor may register further bean definitions
 * which in turn define BeanFactoryPostProcessor instances.
 *
 * @author Juergen Hoeller
 * @since 3.0.1
 * @see org.springframework.context.annotation.ConfigurationClassPostProcessor
 */
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {

    /**
     * Modify the application context's internal bean definition registry after its
     * standard initialization. All regular bean definitions will have been loaded,
     * but no beans will have been instantiated yet. This allows for adding further
     * bean definitions before the next post-processing phase kicks in.
     * @param registry the bean definition registry used by the application context
     * @throws org.springframework.beans.BeansException in case of errors
     */
    void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;

}

這個接口擴展了標準的BeanFactoryPostProcessor 接口,允許在普通的BeanFactoryPostProcessor接口實現類執行之前註冊更多的BeanDefinition。特別地是,BeanDefinitionRegistryPostProcessor可以註冊BeanFactoryPostProcessor的BeanDefinition。

postProcessBeanDefinitionRegistry方法可以修改在BeanDefinitionRegistry接口實現類中註冊的任意BeanDefinition,也可以增加和刪除BeanDefinition。原因是這個方法執行前所有常規的BeanDefinition已經被加載到BeanDefinitionRegistry接口實現類中,但還沒有bean被實例化。

1.1.2、BeanFactoryPostProcessor接口

BeanFactory生成後,如果想對BeanFactory進行一些處理,該怎麼辦呢?BeanFactoryPostProcessor接口就是用來處理BeanFactory的。

/**
 * Allows for custom modification of an application context's bean definitions,
 * adapting the bean property values of the context's underlying bean factory.
 *
 * <p>Application contexts can auto-detect BeanFactoryPostProcessor beans in
 * their bean definitions and apply them before any other beans get created.
 *
 * <p>Useful for custom config files targeted at system administrators that
 * override bean properties configured in the application context.
 *
 * <p>See PropertyResourceConfigurer and its concrete implementations
 * for out-of-the-box solutions that address such configuration needs.
 *
 * <p>A BeanFactoryPostProcessor may interact with and modify bean
 * definitions, but never bean instances. Doing so may cause premature bean
 * instantiation, violating the container and causing unintended side-effects.
 * If bean instance interaction is required, consider implementing
 * {@link BeanPostProcessor} instead.
 *
 * @author Juergen Hoeller
 * @since 06.07.2003
 * @see BeanPostProcessor
 * @see PropertyResourceConfigurer
 */
public interface BeanFactoryPostProcessor {

    /**
     * Modify the application context's internal bean factory after its standard
     * initialization. All bean definitions will have been loaded, but no beans
     * will have been instantiated yet. This allows for overriding or adding
     * properties even to eager-initializing beans.
     * @param beanFactory the bean factory used by the application context
     * @throws org.springframework.beans.BeansException in case of errors
     */
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}

這個接口允許自定義修改應用程序上下文的BeanDefinition,調整上下文的BeanFactory的bean屬性值。應用程序上下文可以在BeanFactory的BeanDefinition中自動檢測BeanFactoryPostProcessor bean,並在創建任何其他bean之前應用它們。對於定位於系統管理員的自定義配置文件非常有用,它們將覆蓋應用程序上下文中配置的bean屬性。請參閱PropertyResourceConfigurer及其具體實現,瞭解解決此類配置需求的開箱即用解決方案。BeanFactoryPostProcessor可能與bean定義交互並修改,但永遠不應該將bean實例化。 這樣做可能會導致過早的bean實例化,違反容器執行順序並導致意想不到的副作用。如果需要bean實例交互,請考慮實現BeanPostProcessor接口。

postProcessBeanFactory方法在BeanFactory初始化後,所有的bean定義都被加載,但是沒有bean會被實例化時,允許重寫或添加屬性。

1.2、Bean實例化中的擴展

1.2.1、BeanPostProcessor接口

/**
 * Factory hook that allows for custom modification of new bean instances,
 * e.g. checking for marker interfaces or wrapping them with proxies.
 *
 * <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.
 *
 * <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}.
 *
 * @author Juergen Hoeller
 * @since 10.10.2003
 * @see InstantiationAwareBeanPostProcessor
 * @see DestructionAwareBeanPostProcessor
 * @see ConfigurableBeanFactory#addBeanPostProcessor
 * @see BeanFactoryPostProcessor
 */
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.
     * @param bean the new bean instance
     * @param beanName the name of the bean
     * @return the bean instance to use, either the original or a wrapped one;
     * if {@code null}, no subsequent BeanPostProcessors will be invoked
     * @throws org.springframework.beans.BeansException in case of errors
     * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
     */
    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

    /**
     * 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.
     * @param bean the new bean instance
     * @param beanName the name of the bean
     * @return the bean instance to use, either the original or a wrapped one;
     * if {@code null}, no subsequent BeanPostProcessors will be invoked
     * @throws org.springframework.beans.BeansException in case of errors
     * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
     * @see org.springframework.beans.factory.FactoryBean
     */
    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

}

這個接口,允許自定義修改新的bean實例,例如檢查標記接口或用代理包裝,注意,如果有相互依賴的bean,這裏可能無法使用代理。

postProcessBeforeInitialization方法,在任何bean初始化回調(如InitializingBean的afterPropertiesSet或自定義init方法)之前,將此BeanPostProcessor應用於給定的新的bean實例。 這個bean已經被填充了屬性值。 返回的bean實例可能是原始的包裝器。

postProcessAfterInitialization方法,在Bean初始化回調(如InitializingBean的afterPropertiesSet或自定義init方法)之後,將此BeanPostProcessor應用於給定的新bean實例。 這個bean已經被填充了屬性值。 返回的bean實例可能是原始的包裝器。這個方法也會在InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation方法生成對象後再次不讓他生成對象(具體可以參考Spring生成bean的過程)。

二、用來感知IOC容器的各種Aware擴展

2.1、BeanNameAware

實現該接口並重寫void setBeanName(String var1)方法;獲取該bean在BeanFactory配置中的名字

2.2、ApplicationContextAware

實現該接口,並重寫setApplicationContext(ApplicationContext applicationContext)方法,獲取spring 上下文環境的對象,然後通過該上下文對象獲取spring容器中的bean對象

2.3、BeanFactoryAware

實現該接口,並重寫void setBeanFactory(BeanFactory beanFactory) 方法,Bean獲取配置他們的BeanFactory的引用

2.4、ServletContextAware

實現該接口,並重寫void setServletContext(ServletContext servletContext)方法;獲取servletContext容器。

2.5、ResourceLoaderAware

實現該接口,並重寫void setServletContext(ServletContext servletContext)方法;獲取ResourceLoader對象,便能夠通過它獲得各種資源。

參考

http://blog.gavinzh.com/2017/11/20/spring-develop-summary/

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