1. 程式人生 > >Spring Bean常用擴充套件介面

Spring Bean常用擴充套件介面

一、前言

    1、Spring框架運用了非常多的設計模式,從整體上看,它的設計嚴格遵循了OCP---開閉原則,即         【1】保證對修改關閉,即外部無法修改Spring整個運作的流程
        【2】提供對擴充套件開放,即可以通過繼承、實現Spring提供的眾多抽象類與介面來改變類載入的行為

二、BeanNameAware、ApplicationContextAware和BeanFactoryAware

    1、實現BeanNameAware介面,在載入過程中可以獲取到該Bean的ID
    2、實現ApplicationContextAware介面,在載入過程中可以獲取到ApplicationContext上下文     3、實現BeanFactroyAware介面,在載入過程中可以獲取到該Bean的BeanFactory package XXX;
import org.springframework.beans.BeansException;import org.springframework.beans.factory.BeanFactory;import org.springframework.beans.factory.BeanFactoryAware;import org.springframework.beans.factory.BeanNameAware;import org.springframework.beans.factory.InitializingBean;import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;import org.springframework.stereotype.Service;//aware:可感知到的@Servicepublicclass BeanTest implements BeanNameAware, ApplicationContextAware,        BeanFactoryAware,InitializingBean {    private static String beanName;    private static ApplicationContext applicationContext
;
    private static ApplicationContext parentApplicationContext;    private static BeanFactory beanFactory;    /**     * 執行順序:1     */    @Override    public void setBeanName(String name) {        System.out.println("setBeanName(...)");//當前Bean的名稱"BeanTest"        this.beanName = name;    }    /**     * 執行順序:2     */    @Override    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {        System.out.println("setBeanFactory(...)");        this.beanFactory = beanFactory;    }    /**     * 執行順序:3     */    @Override    public void setApplicationContext(ApplicationContext applicationContext)            throws BeansException {        System.out.println("setApplicationContext(...)");        this.applicationContext = applicationContext;        this.parentApplicationContext = applicationContext.getParent();    }    /**     * 執行順序:4     */    @Override    public void afterPropertiesSet() throws Exception {        System.out.println("afterPropertiesSet()");    }}

三、InitialingBean和DisposableBean -- 舉例ExtConsumerConfig

    1、initialingBean是一個介面,提供了唯一的方法afterpropertiesSet()
    2、DisposibleBean也是一個介面,提供了唯一的方法destory()
        【1】執行順序:介面優先於配置,即initialingBean>init-method;DisposibleBean>destroy-method
        【2】執行機制:initialingBean和DisposibleBean底層使用型別強轉.方法名()進行直接呼叫;init-method和destroy-method使用反射 package XX;import org.springframework.beans.factory.DisposableBean;import org.springframework.beans.factory.InitializingBean;import org.springframework.stereotype.Service;@Servicepublicclass InitialingBeanAndDisposableBeanTest implements InitializingBean,        DisposableBean {    private Integer age;    public void setAge(Integer age) {        this.age = age;        System.out.println("setAge()");//如果在XML中配置了property    }    @Override    public void destroy() throws Exception {        System.out.println("desrroy()");    }    /**     * 當前Bean(InitialingBeanAndDisposableBeanTest)的所有屬性設定完成後呼叫     */    @Override    public void afterPropertiesSet() throws Exception {        System.out.println("afterPropertiesSet()");    }    //以上列印順序:setAge()->afterPropertiesSet()->destroy()}

四、FactoryBean

    1、傳統Spring容器載入一個Bean的整個過程都是由Spring控制的,開發者除了設定Bean的相關屬性外,沒有太多自主權     2、FactoryBean改變了這一點,開發者可以個性化的定製自己想要例項化出來的Bean
  IAnimal介面: publicinterface Animal {    public abstract void say();}   Cat實現類: publicclass Cat implements Animal {    @Override    public void say() {        System.out.println("cat.say()");    }}   Dog實現類: publicclass Dog implements Animal {    @Override    public void say() {        System.out.println("Dog.say()");    }}  FactoryBean實現類: package XXX;import org.springframework.beans.factory.FactoryBean;@Servicepublicclass FactoryBeanTest implements FactoryBean<Animal> {    private static String name = "cat"// 可以在xml中配置    @Override    public Animal getObject() throws Exception {        if("cat".equals(name)){            return new Cat();        }else if ("dog".equals(name)) {            return new Dog();        }        return null;    }    @Override    public Class<?> getObjectType() {        return Animal.class;    }    @Override    public boolean isSingleton() {        return true;// 返回單例    }} JunitTest(XML中配置省略,把FactoryBeanTest配置到Bean即可 || 或者用@Service註解): package XX;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;publicclass JunitTest {    @Test    public void test() {        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("config/spring/beans.xml");        //此處得到的是[email protected],可見得到了具體的實現類        Object object = applicationContext.getBean("factoryTest");        Animal animal = (Animal) object;        // 結果為:Cat.say()        animal.say();    }}

五、BeanPostProcessor -- 舉例:AnnotationBeanProcessor

    1、之前的initializinngBean、DisposableBean、init-method、destroy-method、FactoryBean都是針對單個Bean控制其初始化的操作
    2、BeanPostProcessor則可以針對每個(所有Bean載入前後都會調下面方法)Bean生成前後執行一些邏輯;有兩個介面:
        【1】postProcessorBeforeInitializing:在初始化Bean之前執行
        【2】postProcessorAfterInitializing:在初始化Bean之後執行     3、單個Bean生命週期如下(從下面列印日誌可以看出BeanTest類的執行順序):
package XX;import org.springframework.beans.BeansException;import org.springframework.beans.factory.config.BeanPostProcessor;import org.springframework.stereotype.Service;@Servicepublicclass BeanPostProcessorTest implements BeanPostProcessor{    /**     * 每個Bean的生成前都會呼叫     */    @Override    public Object postProcessBeforeInitialization(Object bean, String beanName)            throws BeansException {        System.out.println("BeanPostProcessorTest.postProcessBeforeInitialization()");        return bean;    }    /**     * 每個Bean生成過程中,如果有Bean實現自InitializingBean或者配置了init-method方法,會執行     */    /**     * 每個Bean生成後都會呼叫     */    @Override    public Object postProcessAfterInitialization(Object bean, String beanName)            throws BeansException {        System.out.println("BeanPostProcessorTest.postProcessAfterInitialization()");        return bean;    }}

六、BeanFactoryPostProcessor

    1、實現自BeanFactoryPostProcessor,即可以在Spring建立Bean之前,讀取Bean的元屬性,並根據需要對元屬性進行修改,比如將Bean的scope從singleton改變為prototype
    2、BeanFactoryPostProcessor的優先順序高於BeanPostProcessor
    3、BeanFactoryPostProcessor的postProcessorBeanFactory()方法只會執行一次
package XX;import org.springframework.beans.BeansException;import org.springframework.beans.MutablePropertyValues;import org.springframework.beans.factory.config.BeanDefinition;import org.springframework.beans.factory.config.BeanFactoryPostProcessor;import org.springframework.beans.factory.config.ConfigurableBeanFactory;import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;import org.springframework.stereotype.Service;@Servicepublicclass BeanFactoryPostProcessorTest implements BeanFactoryPostProcessor {    /**     * 獲取Bean元屬性並修改等操作     */    @Override    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {        System.out.println("postProcessBeanFactory(...)");        //修改元屬性scope        BeanDefinition beanDefinition = beanFactory.getBeanDefinition("systemParamInit");        System.out.println("scope for systemParamInit before : " + beanDefinition.getScope());        beanDefinition.setScope(ConfigurableBeanFactory.SCOPE_PROTOTYPE);        System.out.println("scope for systemParamInit after : " + beanDefinition.getScope());        //獲取Bean的屬性引數並列印        MutablePropertyValues mutablePropertyValues = beanDefinition.getPropertyValues();        System.out.println("systemParamInit properties :" + mutablePropertyValues);    }}

七、InstantiationAwareBeanPostProcessor

    1、InstantiationAwareBeanPostProcessor又代表了另外一個Bean的生命週期:例項化
    2、例項化 --- 例項化的過程是一個建立Bean的過程,即呼叫Bean的建構函式,單例的Bean放入單例池中
      初始化 --- 初始化的過程是一個賦值的過程,即呼叫Bean的setter,設定Bean的屬性
    3、之前的BeanPostProcessor作用於2過程,現在這個類則作用於1過程 package XX;import java.beans.PropertyDescriptor;import org.springframework.beans.BeansException;import org.springframework.beans.PropertyValues;import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;import org.springframework.stereotype.Service;@Servicepublicclass InstantiationAwareBeanPostProcessorTest implements InstantiationAwareBeanPostProcessor {    @Override    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {        System.out.println("InstantiationAwareBeanPostProcessorTest.postProcessBeforeInitialization()");        return bean;    }    @Override    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {        System.out.println("InstantiationAwareBeanPostProcessorTest.postProcessAfterInitialization()");        return bean;    }    @Override    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {        System.out.println("InstantiationAwareBeanPostProcessorTest.postProcessBeforeInstantiation()");        return beanClass;    }    @Override    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {        System.out.println("InstantiationAwareBeanPostProcessorTest.postProcessAfterInstantiation()");        return true;    }    @Override    public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {        return pvs;    }}