spring--扩展点

扩展点:
BeanFactoryPostProcessor 构建 BeanFactory后调用,此时BeanFactory , BeanDefinition 已经解析完毕。
BeanPostProcessor 初始化 Bean 对象时调用,所有bean的构建都会调用这个接口的两个方法。两个方法参数传入的bean属性都已经注入完毕。
InitializingBean Bean 实例创建后,所有的属性注入完毕后调用。
定义bean时可以指定init-method  和 destory-method 方法
InstantiationAwareBeanPostProcessor   bean包装类初始化时调用方法

DisposableBean Bean 实例销毁时调用

扩展点调用顺序:
1、调用 BeanFactoryPostProcessor 子类的 postProcessBeanFactory() 方法(工厂必须先创建),这里beanFactory 已经创建,beanDefinition已经解析完毕。
2、调用bean 的构造方法。属性没有初始化(使用的都是默认值),依赖没有注入。
3、调用 BeanPostProcessor.postProcessBeforeInitialization() 方法。(所有bean初始化都会调用)
4、调用 InstantiationAwareBeanPostProcessor.postProcessBeforeInitialization() 方法。(所有bean初始化都会调用)
5、调用bean 定义的 init-method 方法(具体到某个bean的初始化)。
6、如果bean 实现了 InitializingBean 接口,调用 InitializingBean.afterPropertiesSet() 方法(具体到某个bean的初始化)。
7、调用 BeanPostProcessor.postProcessAfterInitialization() 方法。(所有bean初始化都会调用)
8、调用 InstantiationAwareBeanPostProcessor.postProcessAfterInitialization() 方法。(所有bean初始化都会调用)

9、bean 销毁,先调用 destory-method 方法,如果bean实现了DisposableBean接口,再调用DisposableBean.destroy() 方法。


1、BeanFactoryPostProcessor

此接口只有一个方法:
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
所以就是使用ConfigurableListableBeanFactory 进行扩展。

扩展方式:
这个扩展的地方就是调用 ConfigurableListableBeanFactory 方法进行扩展。
ConfigurableListableBeanFactory 可以分析和修改、预初始化单例Bean,并且可以修改已有的BeanDifinition属性和类型

调用地方:
所有实现接口BeanFactoryPostProcessor 的bean 都在这里被调用
AbstractApplicationContext.invokeBeanFactoryPostProcessors(beanFactory);

使用场景:
修改bean definition
修改注入类型的注入实例

ConfigurableListableBeanFactory 源码分析:

public interface ConfigurableListableBeanFactory
		extends ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory {

	/**
	 * 忽略给定类型依赖的自动注入
	 */
	void ignoreDependencyType(Class type);

	/**
	 * 忽略给定接口类型的自动注入
	 *	这种特定方式通常被用于使用其它方式解决应用上下文依赖注册。如:BeanFactory通过 BeanFactoryAware 注册,ApplicationContext 通过 ApplicationContextAware 来注册。
	 *	默认情况只有 BeanFactoryAware 接口是被忽略的。调用此方法忽略接口依赖自动注入。
	 */
	void ignoreDependencyInterface(Class ifc);

	/**
	 * 指定依赖的类型,使用 autowiredValue 对象注入。
	 * 预留给 factory/context 类型注入,但是工厂中没有这类bean 定义。
	 */
	void registerResolvableDependency(Class dependencyType, @Nullable Object autowiredValue);

	/**
	 * 确定指定bean是否有自动注入的资格,被注入到声明依赖匹配的类的其它bean中
	 */
	boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor)
			throws NoSuchBeanDefinitionException;

	/**
	 * 获取bean 的 BeanDefinition,可以访问属性值和构造方法参数。
	 * 返回值不是一个副本,是注册在factory中原始的definition object。意味着可以修改为其它更多的特定类型。
	 */
	BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

	/**
	 * 获取factory 管理所有bean 的beanName的统一视图。
	 */
	Iterator getBeanNamesIterator();

	/**
	 * 清除merged bean 定义缓存,删除那些没有资格进行完整元数据缓存的bean。
	 * 当解析的bean definitions被修改了,如调用了 BeanFactoryPostProcessor 方法修改了bean definition。
	 * 注意:此时的bean的元数据对已经创建的bean,是要保留的。
	 */
	void clearMetadataCache();

	/**
	 * 冻结所有的 bean definition, 不让在后面处理修改。
	 */
	void freezeConfiguration();

	/**
	 * 查询 Configuration 是否被冻结
	 */
	boolean isConfigurationFrozen();

	/**
	 * 确保所有的非惰性单例(non-lazy-init singletons)全部实例化。用于解决循环依赖问题。
	 *	如果需要,通过在factory 设置完成时调用
	 */
	void preInstantiateSingletons() throws BeansException;

}
在spring 源码中有使用 ConfigurableListableBeanFactory 类的方法:
AbstractApplicationContext.refresh() 方法中调用的prepareBeanFactory() 方法。
如:PropertyResourceConfigurer   就是一个内置的BeanFactoryPostProcessor实现,实现类是PropertySourcesPlaceholderConfigurer。

测试:

依赖接口及实现
/**
 * 依赖接口
 */
public interface TestServerInterface {
    void m();
}

@Component
public class TestServer2 implements TestServerInterface {

    @Autowired
    private Other o;

    @Override
    public void m() {
        System.out.println("this is server2");
    }

    public Other getO() {
        return o;
    }

    public void setO(Other o) {
        this.o = o;
    }
}

接口实现类依赖的Other 类:

@Component
public class Other {

    public void m(){
        System.out.println("other m");
    }

}

TestServer 依赖 TestServerInterface 子类

@Component
public class TestServer {

    private String name="default";

    @Autowired
    private TestServerInterface t;

    public void test(){
        t.m();
        System.out.println("spring extend test");
    }

    @PostConstruct
    public void before(){
        System.out.println("init-method........");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public TestServerInterface getT() {
        return t;
    }

    public void setT(TestServerInterface t) {
        this.t = t;
    }
}

BeanFactoryPostProcessor  实现类

/**
 * 构建 BeanFactory 完成后调用,此时beanFactory 已经创建,beanDefinition已经解析完毕。
 *
 * 可以修改bean
 * 可以获取beandefinition,修改bean 的配置
 *
 * 参数是ConfigurableListableBeanFactory,体现了不同BeanFactory
 */
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        System.out.println("BeanFactoryPostProcessor------------");

        /**
         * 修改注入类型
         * 如果此bean还依赖其它的bean的话,那么依赖的bean是null,因为 finishBeanFactoryInitialization 组建bean之间的关系是在这个方法中调用的。
         */
        TestServerInterface t = (TestServerInterface)configurableListableBeanFactory.getBean("testServer2");
        configurableListableBeanFactory.registerResolvableDependency(TestServerInterface.class, t);

        //手动注入Other 对象
        TestServer2 t2 = (TestServer2)t;
        t2.setO(configurableListableBeanFactory.getBean(Other.class));

        /**
         * 修改bean 属性
         */
        //修改beandefinition 的属性注入
        BeanDefinition tb = configurableListableBeanFactory.getBeanDefinition("testServer");
        MutablePropertyValues propertyValues = tb.getPropertyValues();
        propertyValues.addPropertyValue("name","new name");

        System.out.println("BeanFactoryPostProcessor############");
    }
}

测试代码(省)

测试总结:

测试:
1、获取testServer ,testServer 的name值被修改为 new name
2、接口TestServerInterface 如果有两个实现类,那么启动时就不知道要注入那一个,在postProcessBeanFactory 方法中,定义了此接口使用 name 为 testServer2 的bean 注入,就解决了这个问。
3、在 postProcessBeanFactory()方法中获取bean,如果还依赖其它的bean的话,那么依赖的bean是不会被注入的,这个时候就要手动注入了要么也调用一下 configurableListableBeanFactory.registerResolvableDependency()  方法,因为 finishBeanFactoryInitialization()方法才是组建bean之间的关系的地方。(见代码手动注入Other)
4、如果有多个BeanFactoryPostProcessor类型的bean,可以使用 @Order()注解来指定调用顺序。


2、BeanPostProcessor

初始化 Bean 对象时调用,所有bean的构建都会调用这个接口的两个方法。两个方法参数传入的bean属性都已经注入完毕。


使用场景:
可以修改bean的属性,
可以给bean生成一个动态代理实例等等。一些Spring AOP的底层处理也是通过实现BeanPostProcessor来执行代理包装逻辑的。

BeanPostProcessor 源码分析:

public interface BeanPostProcessor {

	/**
	 * 所有 bean 初始化之前调用,bean属性已经被填充,所有属性及依赖全部注入。
	 * 返回的bean包装类或者是原始bean。
	 */
	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

	/**
	 * 所有 bean 初始化之后调用。所有属性及依赖全部注入。
	 * 传入的bean属性已经被填充。
	 * 返回的bean包装类或者是原始bean。
	 * 从spring 2.0开始,FactoryBean 会被调用两次,一次是FactoryBean 本身,一次是getObject() 创建bean。
	 * 		
	 */
	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

}
这两个方法区别就是被调用的地方不同,一个是调用bean init-method 之前一个是init-method 之后。

AOP 就是对这些扩展点的使用。


注:

BeanFactoryPostProcessor.postProcessBeanFactory()调用栈

AbstractApplicationContext.refresh() 方法通过调用 invokeBeanFactoryPostProcessors(beanFactory);就是调用postProcessBeanFactory() 方法的入口。


AbstractApplicationContext.refresh()方法中调用的finishBeanFactoryInitialization(beanFactory) 方法中调用了preInstantiateSingletons()方法,确保所有的单例都实例化。所以后面的调用顺序就是在bean实例化之后初始化bean的时候调用了。

你可能感兴趣的:(spring)