Spring之ApplicationContextAware、InitializingBean

1、ApplicationContextAware接口

1.1、当一个类实现了这个接口之后,这个类就可以方便地获得ApplicationContext对象。

1.2、Spring发现某个Bean实现了ApplicationContextAware接口,Spring容器会在创建该Bean之后,自动调用该Bean的setApplicationContextAware()方法,调用该方法时,会将容器本身ApplicationContext对象作为参数传给该方法。
————————————————

2、InitializingBean 接口

当一个类实现这个接口之后,Spring启动时,初始化Bean时,若该Bean实现InitializingBean接口,则会自动调用afterPropertiesSet()方法,完成一些用户自定义的初始化操作。
import com.app.rebsemexcelimport.factory.validator.ExcelDataImportValidator;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

@Component
public class ExcelDataImportValidatorFactory implements ApplicationContextAware, InitializingBean {
    /**
     * Ioc Container.
     */
    private ApplicationContext applicationContext;

    private Map<Integer, ExcelDataImportValidator> handlerMap
        = new HashMap<>();

    @Override
    public void afterPropertiesSet() throws Exception {
        Map<String, ExcelDataImportValidator> handlerMap = applicationContext.getBeansOfType
            (ExcelDataImportValidator.class);
        handlerMap.values().forEach(this::accept);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    public ExcelDataImportValidator get(Integer gfbrmpModule) {
        return handlerMap.get(gfbrmpModule);
    }

    private void accept(ExcelDataImportValidator element) {
        handlerMap.put(element.getGfbrmpModule(), element);
    }
}

3、同样配置Bean时使用init-method也可以实现类似的操作

<bean id = "ExcelDataImportValidatorFactory" class = com.app.rebsemexcelimport.factory" init-method="testInit">
        <property name="id" value="#{1111111}" />
        <property name="name" value="${test.springEL}" />
        <property name="age" value="#{10+8}" /> // SpringEL表达式
        <property name="sex" value="false" />

————————————————
上面就是简单模拟了几个属性

在spring初始化bean的时候,如果该bean是实现了InitializingBean接口,并且同时在配置文件中指定了init-method,系统则是先调用afterPropertiesSet方法,然后在调用init-method中指定的方法。

注意:
1、Spring是通过反射来调用init-method指定方法,而实现InitializingBean接口是直接调用afterPropertiesSet方法,所以后者效率高,但使用init-method方式减少对Spring的依赖。
2、如果调用afterPropertiesSet方法时出错,则不会再调用init-method指定的方法。   
————————————————
简单介绍下Spring afterPropertiesSet方法与init-method方法

1、init-method方法,初始化bean的时候执行,可以针对某个具体的bean进行配置。init-method需要在applicationContext.xml配置文档中bean的定义里头写明。
例如:<bean id="TestBean" class="com.app.util.TestBean" init-method="init"></bean> 这样,当TestBean在初始化的时候会执行TestBean中定义的init方法。   2、afterPropertiesSet方法,初始化bean的时候执行,可以针对某个具体的bean进行配置。afterPropertiesSet 必须实现 InitializingBean接口。实现 InitializingBean接口必须实现afterPropertiesSet方法。   3、BeanPostProcessor,针对所有Spring上下文中所有的bean,可以在配置文档applicationContext.xml中配置一个BeanPostProcessor,
然后对所有的bean进行一个初始化之前和之后的代理。BeanPostProcessor接口中有两个方法: postProcessBeforeInitialization和postProcessAfterInitialization。
postProcessBeforeInitialization方法在bean初始化之前执行,
postProcessAfterInitialization方法在bean初始化之后执行。   总之,afterPropertiesSet 和init
-method之间的执行顺序是afterPropertiesSet 先执行,init-method 后执行。从BeanPostProcessor的作用,可以看出最先执行的是postProcessBeforeInitialization,然后是afterPropertiesSet,然后是init-method,然后是postProcessAfterInitialization。 ————————————————

 

posted @ 2021-03-25 15:10  Gentleman-cx  阅读(564)  评论(0编辑  收藏  举报