Spring注解驅(qū)動開發(fā)(二)

https://github.com/cuzz1/learn-demo/tree/master/demo-05-spring-annotation

1. 聲明周期@Bean指定初始化和銷毀方法

1 ) Bean的生命周期

Bean的創(chuàng)建、初始化和銷毀是由容器幫我們管理的

我們可以自定義初始化和銷毀方法,容器在進行到當前生命周期的時候來調(diào)用我買自定義的初始化和銷毀方法

構(gòu)造(對象創(chuàng)建)

? 單實例: 在容器啟動的時候創(chuàng)建

? 多實例: 在每次獲取的時候創(chuàng)建對象

2 ) 指定初始化方法

初始化:對象創(chuàng)建完成后,并賦值化,調(diào)用初始化方法

銷毀:單實例是在容器關(guān)閉的時候銷毀,多實例容器不會管理這個Bean,容器不會調(diào)用銷毀方法

編寫一個Car類

/**
 * @Author: cuzz
 * @Date: 2018/9/23 21:20
 * @Description:
 */
public class Car {

    public Car () {
        System.out.println("car constructor...");
    }

    public void init() {
        System.out.println("car...init...");
    }

    public void destroy() {
        System.out.println("car...destroy...");
    }
}

在xml中我們可以指定init-methoddestroy-method方法,如

<bean id="car" class="com.cuzz.bean.Car" init-method="init" destroy-method="destroy"></bean>

使用注解我們可以

/**
 * @Author: cuzz
 * @Date: 2018/9/24 12:49
 * @Description: 配置類
 */
@Configuration
public class MainConfigOfLifecycle {

    @Bean(initMethod = "init", destroyMethod = "destroy")
    public Car car() {
        return new Car();
    }

}

測試

/**
 * @Author: cuzz
 * @Date: 2018/9/24 13:00
 * @Description:
 */
public class IOCTestLifeCycle {

    @Test
    public void test01() {
        // 創(chuàng)建ioc容器
        AnnotationConfigApplicationContext applicationContext =
                new AnnotationConfigApplicationContext(MainConfigOfLifecycle.class);
        System.out.println("容器創(chuàng)建完成...");
        // 關(guān)閉容器
        System.out.println("--->開始關(guān)閉容器");
        applicationContext.close();
        System.out.println("--->已經(jīng)關(guān)閉容器");
    }
}

可以看出先創(chuàng)建car,再調(diào)用init方法,在容器關(guān)閉時銷毀實例

car constructor...
car...init...
容器創(chuàng)建完成...
--->開始關(guān)閉容器
car...destroy...
--->已經(jīng)關(guān)閉容器

在配置數(shù)據(jù)源的時候,有很多屬性賦值,銷毀的時候要把連接給斷開

2. 生命周期InitializingBean和DisposableBean

1 ) InitializingBean

可以通過Bean實現(xiàn)InitializingBean來定義初始化邏輯,是設(shè)置好所有屬性會調(diào)用afterPropertiesSet()方法

public interface InitializingBean {

    /**
     * Invoked by a BeanFactory after it has set all bean properties supplied
     * (and satisfied BeanFactoryAware and ApplicationContextAware).
     * <p>This method allows the bean instance to perform initialization only
     * possible when all bean properties have been set and to throw an
     * exception in the event of misconfiguration.
     * @throws Exception in the event of misconfiguration (such
     * as failure to set an essential property) or if initialization fails.
     */
    void afterPropertiesSet() throws Exception;

}

2)DisposableBean

可以通過Bean實現(xiàn)DisposableBean來定義銷毀邏輯,會調(diào)用destroy()方法

public interface DisposableBean {

    /**
     * Invoked by a BeanFactory on destruction of a singleton.
     * @throws Exception in case of shutdown errors.
     * Exceptions will get logged but not rethrown to allow
     * other beans to release their resources too.
     */
    void destroy() throws Exception;

}

3)例子

編寫一個Cat類

/**
 * @Author: cuzz
 * @Date: 2018/9/24 13:36
 * @Description:
 */
public class Cat implements InitializingBean, DisposableBean{

    public Cat() {
        System.out.println("cat constructor...");
    }


    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("cat...init...");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("cat...destroy...");
    }

}

測試

cat constructor...
cat...init...
容器創(chuàng)建完成...
--->開始關(guān)閉容器
cat...destroy...
--->已經(jīng)關(guān)閉容器

3. 生命周期@PostContruct和@PreDestroy注解

@PostContruct在Bean創(chuàng)建完成并且屬性賦值完成,來執(zhí)行初始化

@PreDestroy在容器銷毀Bean之前通知我們進行清理工作

編寫一個Dog類,并把他注入到配置類中

/**
 * @Author: cuzz
 * @Date: 2018/9/24 14:03
 * @Description:
 */
public class Dog {

    public Dog() {
        System.out.println("dog constructor...");
    }

    @PostConstruct
    public void postConstruct() {
        System.out.println("post construct...");
    }

    @PreDestroy
    public void preDestroy() {
        System.out.println("pre destroy...");
    }
}

測試結(jié)果

dog constructor...
post construct...
容器創(chuàng)建完成...
--->開始關(guān)閉容器
pre destroy...
--->已經(jīng)關(guān)閉容器

4. 生命周期BeanPostProscessor后置處理器

在Bean初始化前后做一些處理

public interface BeanPostProcessor {
    // 在初始化之前工作
    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
    // 在初始化之后工作
    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

}

編寫一個MyBeanPostProcessor實現(xiàn)BeanPostProcessor接口

/**
 * @Author: cuzz
 * @Date: 2018/9/24 14:21
 * @Description: 后置處理器,初始化前后進行處理工作
 */
public class MyBeanPostProcessor implements BeanPostProcessor{
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("--->postProcessBeforeInitialization..." + beanName +"==>" + bean);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("--->postProcessAfterInitialization..." + beanName +"==>" + bean);
        return bean;
    }
}

測試

--->postProcessBeforeInitialization...org.springframework.context.event.internalEventListenerProcessor==>org.springframework.context.event.EventListenerMethodProcessor@1dc67c2
--->postProcessAfterInitialization...org.springframework.context.event.internalEventListenerProcessor==>org.springframework.context.event.EventListenerMethodProcessor@1dc67c2
--->postProcessBeforeInitialization...org.springframework.context.event.internalEventListenerFactory==>org.springframework.context.event.DefaultEventListenerFactory@2bd765
--->postProcessAfterInitialization...org.springframework.context.event.internalEventListenerFactory==>org.springframework.context.event.DefaultEventListenerFactory@2bd765
cat constructor...
--->postProcessBeforeInitialization...cat==>com.cuzz.bean.Cat@1d3b207
cat...init...
--->postProcessAfterInitialization...cat==>com.cuzz.bean.Cat@1d3b207
容器創(chuàng)建完成...
--->開始關(guān)閉容器
cat...destroy...
--->已經(jīng)關(guān)閉容器

在實例創(chuàng)建之前后創(chuàng)建之后會被執(zhí)行

5. 生命周期BeanPostProcessor原理

通過debug到populateBean,先給屬性賦值在執(zhí)行initializeBean方法

try {
    populateBean(beanName, mbd, instanceWrapper);
    if (exposedObject != null) {
        exposedObject = initializeBean(beanName, exposedObject, mbd);
    }
}

initializeBean方法時,

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {


    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        // 執(zhí)行before方法
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }
    ...
    try {
        // 執(zhí)行初始化
        invokeInitMethods(beanName, wrappedBean, mbd);
    }

    if (mbd == null || !mbd.isSynthetic()) {
        // 執(zhí)行after方法
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }
    return wrappedBean;
}

Spring底層對BeanPostProcessor的使用

Bean賦值、注入其他組件、@Autowired、生命周期注解功能、@Async等等都使用到了BeanPostProcessor這個接口的實現(xiàn)類,很重要

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容