目录

一、全局与容器生命周期回调

二、BeanDefinitionRegistryPostProcessor扩展

1.单个使用示例

2.多个使用(指定顺序)

三、BeanFactoryPostProcessor扩展

1.使用示例

2.使用BeanFactoryPostProcessor的注意点

四、BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor扩展点的执行顺序

1.执行BeanDefinitionRegistryPostProcessor实现类中的扩展逻辑

2.执行BeanFactoryPostProcessor中的扩展逻辑

五、BeanPostProcessor扩展

六、Aware接口(获取容器资源)

七、以上扩展点的执行顺序图


Spring提供了容器层级和类层级的扩展,在Bean被初始化或销毁等不同生命周期进行功能的扩展。

  • 在容器层级,Spring提供接口BeanFactoryPostProcessor和BeanPostProcessor,用于容器实例化每个Bean的前后进行功能的扩展;
  • 在类层级,可以通过配置init-method和destory-method(或使用相应的注解)等方式来进行回调,实现Bean在初始化和销毁时的功能扩展。

一、全局与容器生命周期回调

Bean在容器中的基本生命周期包括加载创建存活销毁。很多场景下,需要在Bean实例创建的时候进行一些其他操作,比如占位符的替换,在Bean销毁的时候进行一些资源的释放,这时候就可以使用容器或类层级的扩展点达成。上文中配置init-method和destory-method属性的方式进行扩展是类层级的,只对当前类的Bean生效,如果需要对所有的Bean进行全局的初始化和销毁配置,则在根元素<beans>中定义default-init-method和default-destory-method属性。如果定义了全局性配置,那么就要在所有的Bean类中实现所定义的方法。如果全局和单独的Bean同时进行了配置,那么单独的配置会覆盖全局配置。如果希望通过一个单独的类实例来处理应用中所有Bean的生命周期方法回调,就需要实现BeanFactoryPostProcessor和BeanPostProcessor接口的类,并配置成Bean。继承这两个接口之后,就可以获取容器的配置和资源,进而进行Bean和容器的更多功能扩展,这是在容器层级的扩展

二、BeanDefinitionRegistryPostProcessor扩展

Spring容器启动过程中,会将Bean解析成Spring内部的BeanDefinition对象,不论是通过xml方式配置的<bean>,还是通过注解配置的@Bean等等最终都会被解析为BeanDefinition对象,有了这个信息Bean工厂才可以对Bean进行实例化、初始化等操作。我们暂且将容器提取配置信息并映射为BeanDefinition实例之后到在Bean真正实例化之前的阶段,称为Bean注册阶段,所有Bean都在这个阶段注册完毕。Spring会先提取已经配置的Bean信息并注册,还为我们提供了BeanDefinitionRegistryPostProcessor接口,我们可以在其postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)方法中调用API注册Bean。你可以把BeanDefinition丢给Bean工厂,然后Bean工厂就会根据这个信息帮你生产一个Bean实例供你使用。BeanDefinition中包含了bean定义的各种信息,如:bean对应的class、scope、lazy信息、dependOn信息、autowireCandidate(是否是候选对象)、primary(是否是主要的候选者)等信息。具体如下:

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {//设置当前bean的父bean名称(对应xml中bean元素的parent属性)void setParentName(@Nullable String parentName);//返回当前bean只当的父bean名称String getParentName();//设置当前bean的class属性(相当于配置bean类名)void setBeanClassName(@Nullable String beanClassName);/*获取bean的类名,如果子定义重写/继承其父类的类名,则这不一定是运行时使用的实际类名。*此外,这可能只是调用工厂方法的类,或者在调用方法的工厂bean引用的情况下,它甚至可能是空的。*因此,不要认为这是运行时的最终bean类型,而只将其用于单个bean定义级别的解析目的。*/String getBeanClassName();//设置bean的作用域void setScope(@Nullable String scope);//获取作用域String getScope();//设置是否懒加载void setLazyInit(boolean lazyInit);//返回当前bean是否被设置为懒加载boolean isLazyInit();//设置当前bean依赖于实例化的bean名称,bean工厂将保证dependsOn指定的bean会在当前bean实例化之前先实例化好void setDependsOn(@Nullable String... dependsOn);//返回当前bean依赖的bean名称String[] getDependsOn();//设置当前bean是否作为其他bean自动注入时的候选者(autowire-candidate属性)void setAutowireCandidate(boolean autowireCandidate);boolean isAutowireCandidate();//设置此bean是否作为自动注入的主要候选者void setPrimary(boolean primary);boolean isPrimary();//指定要使用的工厂bean(如果有)。这是要对其调用指定工厂方法的bean的名称void setFactoryBeanName(@Nullable String factoryBeanName);//返回工厂bean名称(如果有)(对应factory-bean属性)String getFactoryBeanName();/**设置工厂方法(如果有)此方法将使用构造函数参数调用,如果未指定任何参数,则不使用任何参数调用。*该方法将在指定的工厂bean(如果有的话)上调用,或者作为本地bean类上的静态方法调用。*/void setFactoryMethodName(@Nullable String factoryMethodName);String getFactoryMethodName();//获取当前bean的构造器参数值ConstructorArgumentValues getConstructorArgumentValues();//是否有构造器参数值设置信息(对应constructor-arg元素)default boolean hasConstructorArgumentValues() {return !getConstructorArgumentValues().isEmpty();}//获取bean定义时配置的属性值设置信息MutablePropertyValues getPropertyValues();//是否有属性设置信息(对应<property>)default boolean hasPropertyValues() {return !getPropertyValues().isEmpty();}//设置当前bean的初始化方法名(init-method)void setInitMethodName(@Nullable String initMethodName);String getInitMethodName();//设置当前bean的销毁方法名(destory-method)void setDestroyMethodName(@Nullable String destroyMethodName);String getDestroyMethodName();//设置当前bean的role信息void setRole(int role);int getRole();//设置当前bean的描述信息void setDescription(@Nullable String description);String getDescription();//获取当前bean类型解析器ResolvableType getResolvableType();//当前bean是否被设置为单例boolean isSingleton();//当前bean是否被设置为多例(原型)作用域boolean isPrototype();//当前bean是否被设置为抽象的(<bean>中的abstract属性)boolean isAbstract();//获取bean定义来自的资源的描述(方便出错时显示上下文)String getResourceDescription();BeanDefinition getOriginatingBeanDefinition();
}

1.单个使用示例

如下我们通过在postProcessBeanDefinitionRegistry方法中注册一个Person类的Bean。

public class PersonBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {AbstractBeanDefinition personBeanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Person.class).addPropertyValue("age", 10).addPropertyValue("name", "张无忌").getBeanDefinition();registry.registerBeanDefinition("person", personBeanDefinition);}@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {}}

我们需要将这个PersonBeanDefinitionRegistryPostProcessor类告诉容器,配置如下:

<bean id="personBDRPP" class="com.mec.spring.medol.PersonBeanDefinitionRegistryPostProcessor"></bean> 

测试如下:

public static void main(String[] args) {    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");context.registerShutdownHook();Person p = (Person) context.getBean("person");System.out.println(p);
}

2.多个使用(指定顺序)

当存在多个的时候,我们可以通过实现PriorityOrdered接口和Orderd接口来指定执行顺序,如下:

public class AddressBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor, Ordered {@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {AbstractBeanDefinition addressBeanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Address.class).getBeanDefinition();registry.registerBeanDefinition("address", addressBeanDefinition);System.out.println("address注册完毕");}@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {}@Overridepublic int getOrder() {return 1;}
}
public class PersonBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor, Ordered {@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {AbstractBeanDefinition personBeanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Person.class).addPropertyValue("age", 10).addPropertyValue("name", "张无忌").addPropertyReference("address", "address").getBeanDefinition();registry.registerBeanDefinition("person", personBeanDefinition);System.out.println("person注册完毕");}@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {}@Overridepublic int getOrder() {return 0;}
}

Ordered接口通过getOrder()方法指定执行顺序,从结果可以看出,返回值较小的是先执行的。

三、BeanFactoryPostProcessor扩展

这个接口是Spring在注册完所有bean之后就为我们预留的接口,同样此时bean还没有被实例化。此扩展点可以对Bean的配置进行读取和修改,Spring会获取容器中注册的所有该接口的实现类并调用他们的postProcessBeanFactory方法。当然如果同时存在多个的话则可以通过PriorityOredred接口和Ordered接口排序。

1.使用示例

先配置一个bean如下:

<bean id="person" class="com.mec.spring.medol.Person"><property name="age" value="18"></property><property name="name" value="张三"></property>
</bean>

创建BeanFactoryPostProcessor接口的实现类,如下:

public class HelloBeanFactoryPostProcessor implements BeanFactoryPostProcessor {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {BeanDefinition beanDefinition = beanFactory.getBeanDefinition("person");MutablePropertyValues pv = beanDefinition.getPropertyValues();pv.addPropertyValue("age", 100);pv.addPropertyValue("name", "张三丰");}
}

将这个HelloBeanFactoryPostProcessor类告诉容器:

<bean id="helloBFPP" class="com.mec.spring.medol.HelloBeanFactoryPostProcessor"></bean>

测试得到结果如下:

框架本身的典型应用就是PropertySourcesPlaceholderConfigurer这个类,它间接地实现了BeanFactoryProcessor,它地作用是对所有Bean定义的占位符替换成对应的值,以数据库的配置为例,我们常将数据库的连接信息配置在一个properties文件中。

cfg.properties

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mystudy
jdbc.username=root
jdbc.password=root
<bean id="propertyConfigurer" class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"><property name="locations" value="cfg.properties"></property>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close"><!-- ${}占位符 --><property name="driverClassName" value="${jdbc.driverClassName}"></property><property name="url" value="${jdbc.url}"></property><property name="username" value="${jdbc.username}"></property><property name="password" value="${jdbc.password}"></property>
</bean>

测试如下:

public static void main(String[] args) {ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");context.registerShutdownHook();DataSource dataSource = (DataSource) context.getBean("dataSource");try {Connection connection = dataSource.getConnection();String sql = "select * from t_user where name=?";PreparedStatement ps = connection.prepareStatement(sql);ps.setString(1, "杨过");ResultSet rs = ps.executeQuery();while (rs.next()) {int id = rs.getInt("id");String name = rs.getString("name");String sex = rs.getString("sex");System.out.println(id + "\t" + name + "\t" + sex);}connection.close();} catch (SQLException e) {e.printStackTrace();}
}

2.使用BeanFactoryPostProcessor的注意点

  1. 在postProcessBeanFactory方法中禁止去通过容器获取其他Bean,此时会导致Bean的提前初始化会出现一些意想不到的问题;
  2. 别再postProcessBeanFactory方法中去创建Bean
  3. 将BeanFactoryPostProcessor配置为懒加载是没有意义的,因为容器实例化该接口的实现类时是不考虑这个懒加载属性的,源码中可以体现。

四、BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor扩展点的执行顺序

从容器的启动开始看起,核心方法是refresh()

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)throws BeansException {super(parent);//处理传递的配置文件路径setConfigLocations(configLocations);if (refresh) {//核心方法refresh();}
}
//AbstractApplicationContext类
public void refresh() throws BeansException, IllegalStateException {//加锁,避免在执行下面操作时容器启动和关闭synchronized (this.startupShutdownMonitor) {//1.准备工作:记录容器启动时间、设置状态为“已启动”、在上下文环境中初始化占位符prepareRefresh();/*2.这里完成了配置文件的解析工作,从根元素<beans>开始提取了配置信息,转换成对应的对象。*我们配置的<bean>信息当然也会被加载(doLoadBeanDefinitions),注册(registerBeanDefinition)。*注意:这里并没有实例化Bean,而是我们配置的<bean>--->映射为BeanDefinition(这里包含了<bean>下的所有配置信息)*/ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();/*3.这个方法中还是对BeanFactory的一些设置,比如设置工厂的类加载器和其他特征等,*  还添加了一些BeanPostProcessor,比如ApplicationContextAwareProcessor*  还注册了一些特殊的Bean*/prepareBeanFactory(beanFactory);try {/**此时所有bean定义都被加载、注册,但还没有bean被实例化。*该方法目的是AbstractApplicationContext提供给其子类,让其子类覆写该方法用于注册一些特殊的BeanPostProcessor*/postProcessBeanFactory(beanFactory);/* *调用BeanDefinitionRegistryPostProcessor各个实现类的postProcessBeanDefinitionRegistry方法*调用BeanFactoryPostProcessor各个实现类的postProcessBeanFactory(factory)方法*/invokeBeanFactoryPostProcessors(beanFactory);//注册BeanPostProcessor各个实现类到工厂中。这里仅仅是注册,而并没有执行扩展方法registerBeanPostProcessors(beanFactory);initMessageSource();initApplicationEventMulticaster();onRefresh();registerListeners();finishBeanFactoryInitialization(beanFactory);finishRefresh();}catch (BeansException ex) {if (logger.isWarnEnabled()) {logger.warn("Exception encountered during context initialization - " +"cancelling refresh attempt: " + ex);        }destroyBeans();cancelRefresh(ex);throw ex;}finally {resetCommonCaches();}}
}

上面refresh()方法中的invokeBeanFactoryPostProcessors(beanFactory);就是我们所找的方法,该方法源码如下:

//AbstractApplicationContext
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
//这里的getBeanFactoryPostProcessors()方法获取的是AbstractApplicationContext中维护的一个集合
//List<BeanFactoryPostProcessor>,我们可以调用AbstractApplicationContext的addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor)对其进行设置PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory,getBeanFactoryPostProcessors());if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));}
}

下面方法中调用我们自定义的扩展点(BeanFactoryPostProcessor)的postProcessBeanFactory(beanFactory)方法。这个操作是让PostProcessorRegistrationDelegate这个类来做的,这个类的invokeBeanFactoryPostProcessors方法中执行了BeanDefinitionRegistryPostProcessor子类BeanFactoryPostProcessor子类中的扩展方法。针对这两点,源码中分别对应如下:

1.执行BeanDefinitionRegistryPostProcessor实现类中的扩展逻辑

public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {Set<String> processedBeans = new HashSet<>();
//第一步://这里的beanFactory是DefaultListableBeanFactory实例,它实现了BeanDefinitionRegistry接口,if判断成立if (beanFactory instanceof BeanDefinitionRegistry) {BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();//这里循环遍历集合beanFactoryPostProcessors,我们没有手动addBeanFactoryPostProcessor时这个集合是空的for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor;registryProcessor.postProcessBeanDefinitionRegistry(registry);registryProcessors.add(registryProcessor);}else {regularPostProcessors.add(postProcessor);}}List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
//第二步://获取所有BeanDefinitionRegistryPostProcessor实现类对应的beanNamesString[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);for (String ppName : postProcessorNames) {//判断这些类是否实现了PriorityOrdered,若实现了,则创建这些类的实例并将其添加到集合中if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));processedBeans.add(ppName);}}//对这些处理器进行排序sortPostProcessors(currentRegistryProcessors, beanFactory);//将这些添加到registryProcessors集合中registryProcessors.addAll(currentRegistryProcessors);//执行集合中实例的postProcessBeanDefinitionRegistry(registry)方法invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);//清空currentRegistryProcessors集合currentRegistryProcessors.clear();//第三步:这里重新获取的原因是有可能在上述的扩展方法postProcessBeanDefinitionRegistry中又添加了BeanDefinitionRegistryPostProcessor的实现类beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);for (String ppName : postProcessorNames) {if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));processedBeans.add(ppName);}}sortPostProcessors(currentRegistryProcessors, beanFactory);registryProcessors.addAll(currentRegistryProcessors);invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);currentRegistryProcessors.clear();//第四步:boolean reiterate = true;while (reiterate) {reiterate = false;postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);for (String ppName : postProcessorNames) {if (!processedBeans.contains(ppName)) {currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));processedBeans.add(ppName);reiterate = true;}}sortPostProcessors(currentRegistryProcessors, beanFactory);registryProcessors.addAll(currentRegistryProcessors);invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);currentRegistryProcessors.clear();}
//第五步:invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);}else {invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);}
//省略下面处理BeanFactoryPostProcessor的代码
}

上述流程可以看成如下五步:

  1. 第一步:遍历所有通过调用addBeanFactoryPostProcessor方法添加进来的BeanDefinitionRegistryPostProcessor实现类,按添加顺序执行扩展方法,并将其存入registryProcessors集合中;于此同时将通过此法添加的BeanFactoryPostProcessor存到集合regularPostProcessors中。
  2. 第二步:查找所有实现PriorityOrdered接口的实现类,实例化这些实现类,并对他们进行排序,接着执行其中的扩展方法。这些实现类也别添加到registryProcessors集合中了。
  3. 第三步:查找所有实现Ordered接口的实现类,实例化这些类,并对他们进行排序,接着执行其中的扩展方法,将他们也加入到registryProcessors集中了去。
  4. 第四步:这里使用了一个循环,在循环里面又重新获取所有BeanDefinitionRegistryPostProcessor实现类的beanNames,如果又有新的被添加进来,则再次循环,否则退出循环。这样就可以执行完所有postProcessBeanDefinitionRegistry(registry)方法。
  5. 第五步:上述使用的几个集合作用processedBeans(HashSet,主要是为了去重,避面重复执行),registryProcessors(ArrayList,收集所有的BeanDefinitionRegistryPostProcessor实现类),regularPostProcessors(ArrayList,收集通过addBeanFactoryPostProcessor方法添加进来的BeanFactoryPostProcessor实现类),currentRegistryProcessors(ArrayList,成功收集每一步的BeanDefinitionRegistryPostProcessor实现类)。注意:上面前四步中执行的只是BeanDefinitionRegistryPostProcessor实现类的postProcessBeanDefinitionRegistry方法,这一步执行的是这些实现类的postProcessBeanFactory方法

2.执行BeanFactoryPostProcessor中的扩展逻辑

public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
//承接上面代码String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();List<String> orderedPostProcessorNames = new ArrayList<>();List<String> nonOrderedPostProcessorNames = new ArrayList<>();for (String ppName : postProcessorNames) {if (processedBeans.contains(ppName)) {}else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));}else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {orderedPostProcessorNames.add(ppName);}else {nonOrderedPostProcessorNames.add(ppName);}}sortPostProcessors(priorityOrderedPostProcessors, beanFactory);invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());for (String postProcessorName : orderedPostProcessorNames) {orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));}sortPostProcessors(orderedPostProcessors, beanFactory);invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());for (String postProcessorName : nonOrderedPostProcessorNames) {nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));}invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);beanFactory.clearMetadataCache();
}

可以看到上面创建了三个集合分别收集三种的元素:实现PriorityOrdered接口的实现类、实现Ordered接口的bean名称、没有实现排序接口的bean名称。上述流程也可以分如下几步(注意在此之前已经执行完BeanDefinitionRegistryPostProcessor各个实现类的postProcessBeanFactory方法了):

  1. 实例化、排序、执行PriorityOrdered接口实现类的postProcessBeanFactory方法。
  2. 实例化、排序、执行Ordered接口的实现类的postProcessBeanFactory方法。
  3. 实例化、排序、执行没有排序接口的实现类的postProcessBeanFactory方法。

invokeBeanFactoryPostProcessors方法源码如下:

private static void invokeBeanFactoryPostProcessors(Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {for (BeanFactoryPostProcessor postProcessor : postProcessors) {postProcessor.postProcessBeanFactory(beanFactory);}
}

五、BeanPostProcessor扩展

该接口有两个方法:postProcessBeforeInitialization(Object bean, String beanName)postProcessAfterInitialization(Object bean, String beanName)。与BeanFactoryPostProcessor接口不同,此接口的两个方法都是在Bean实例化之后执行的,方法的参数是实例化之后的Bean对象对应的bean名称,拿到Bean对象就可以随意操作该对象,比如可以创建该实例的代理对象等等。

在refresh()方法中,执行完invokeBeanFactoryPostProcessors(beanFactory)方法后紧接着的执行registerBeanPostProcessors(beanFactory)方法,该方法完成的是注册BeanPostProcessor各个实现类到工厂中。这里仅仅是注册,而并没有执行其中的扩展方法。这里的注册操作是委托给PostProcessorRegistrationDelegate类完成的,具体逻辑与invokeBeanFactoryPostProcessors(beanFactory)极其相似。注册的时候会直接排好顺序:

  1. 首先对所有PriorityOrdered接口的实现类进行排序、注册;
  2. 接着对所有Ordered接口的实现类进行排序、注册
  3. 对其他实现类进行注册。

至于BeanPostProcessor接口中方法的调用时机,我们可以打印出方法调用栈信息查看。如下:

public class HelloBeanPostProcessor implements BeanPostProcessor {
//打印该方法的调用栈@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {StackTraceElement stack[] = Thread.currentThread().getStackTrace();for (int i = 0; i < stack.length; i++) {System.out.println(stack[i].getClassName() + " <--->" + stack[i].getMethodName());}return bean;}
}

同样的,添加配置如下:

<bean id="helloBPP" class="com.mec.spring.medol.HelloBeanPostProcessor"></bean>

根据上述打印结果,我们先找到doCreateBean方法的源码,如下:

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)throws BeanCreationException {BeanWrapper instanceWrapper = null;if (mbd.isSingleton()) {instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);}if (instanceWrapper == null) {//Bean的实例化操作instanceWrapper = createBeanInstance(beanName, mbd, args);}//......省略一部分代码Object exposedObject = bean;try {//属性填充,注入依赖populateBean(beanName, mbd, instanceWrapper);exposedObject = initializeBean(beanName, exposedObject, mbd);}catch (Throwable ex) {//....省略一部分代码}//....省略一部分代码
}

上面代码中在依赖注入完毕之后,调用了initializeBean方法,该方法如下:

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {//为Aware实现类设置资源if (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {invokeAwareMethods(beanName, bean);return null;}, getAccessControlContext());}else {invokeAwareMethods(beanName, bean);}Object wrappedBean = bean;if (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);}try {//这个方法内部首先会执行InitializingBean接口实现类的afterPropertiesSet()方法//然后执行bean配置的初始化方法invokeInitMethods(beanName, wrappedBean, mbd);}catch (Throwable ex) {throw new BeanCreationException((mbd != null ? mbd.getResourceDescription() : null),beanName, "Invocation of init method failed", ex);}if (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}return wrappedBean;
}

从上面方法可以看出,在执行bean配置的初始化方法之前,分别调用了applyBeanPostProcessorsBeforeInitialization方法和applyBeanPostProcessorsAfterInitialization方法,如下:

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)throws BeansException {Object result = existingBean;//获取所有的BeanPostProcessor的实现类,他们存储在一个List中List<BeanPostProcessor>for (BeanPostProcessor processor : getBeanPostProcessors()) {//执行其中的前置扩展方法,这相当于bean实例的前置控制链,//前一个postProcessBeforeInitialization方法的返回值会作为下一个被调用的参数,//直到某个postProcessBeforeInitialization方法返回null或者全部执行完毕才会从该方法中返回Object current = processor.postProcessBeforeInitialization(result, beanName);if (current == null) {return result;}result = current;}return result;
}

applyBeanPostProcessorsAfterInitialization方法跟这个几乎一致。所以可以得出结论:postProcessBeforeInitialization方法是在Bean实例化、依赖注入完毕,在初始化(init-method)方法之前调用的,postProcessAfterInitialization方法是在Bean实例化、依赖注入、初始化方法执行完毕后调用的

六、Aware接口(获取容器资源)

SpringIoC容器通过依赖注入降低应用系统的耦合性,所以在应用代码中尽量不要使用容器对象,但是有时候不可避免的需要获取Spring容器的一些资源。Spring提供的一系列Aware后缀的接口用于获取容器的资源和对象,相关接口的实现类能得到Aware后缀前面命名部分的资源对象,进行功能扩展。Aware的意思是知道的、感知的,使用这个命名很形象,是对容器对象的感知。Spring提供的Aware接口如下:

  1. ApplicationContextAware:获取应用上下文,通过setApplicationContext()方法获取ApplicationContext。
  2. BeanFactoryAware:获取对象工厂,通过setBeanFactory()方法得到和获取。
  3. BeanNameAware:获取Bean实例的标识。使用id和name可以指定名字,使用alias可以指定别名,这些名称是维护在容器中的,Bean对象本身并不知道。如果Bean需要获取或修改Bean的名称,就i可以继承BeanNameAware接口,覆写setBeanName()方法。
  4. ApplicationEventPublisherAware:获取事件发布器。ApplicationEventPublisher是ApplicationContext的父接口之一,该接口有两个不同参数的publishEvent()方法,重载用于发布事件,通知与事件匹配的监听器。
  5. BeanClassLoadAware:获取类加载器。
  6. MessageSourceAware:获取MessageSource,用于国际化消息处理。
  7. ResourceLoaderAware:获取资源加载器,可以获取外部资源文件。

因为ApplicationContext接口继承了MessageSource接口、ApplicationEventPublisherAware接口和ResourceLoaderAware,所以类继承ApplicationContextAware就可以获取Spring容器的所有服务,但一般是用到什么接口就去实现什么接口。

依赖注入主要用于解决代码的耦合问题,Spring的理念也是让应用系统对容器依赖程度很低,也就是换个容器,应用代码很容易就可以运行。实际开发中,应尽量减少对Aware的使用,以避免应用的代码和Spring框架紧耦合,这并不是Spring设计的初衷,毕竟Spring Aware是Spring设计用来框架内部使用的。我们可以多使用注解的方式获取容器资源的方式,除了写法上简洁外,也降低了和容器的耦合度。

七、以上扩展点的执行顺序图

Spring【三】容器与Bean扩展点相关推荐

  1. Spring IoC容器与Bean管理18:Bean对象的作用域及生命周期三:对象生命周期;

    说明: (1)本篇博客主要根据案例阐述对象的声明周期: (2)其中,比较重要的是注意下这个对应关系: (3)还有就是调用[registerShutdownHook()]销毁IoC容器: 目录 一:be ...

  2. 【Spring杂烩】探讨Spring向容器注册Bean的三种方式

    探讨Spring向容器注册Bean的三种方式 重点了解@Import实现的三种子方式 前提概要 Spring向容器注册Bean的三种方式 通过@ComponentScan.@Componet 通过@B ...

  3. Spring IoC容器与Bean管理

    Spring IoC容器与Bean管理 一.Spring IoC容器与Bean管理 1.Spring快速入门 IoC控制反转 DI依赖注入 Spring概述 Spring IoC初体验 使用XML方式 ...

  4. Spring IOC容器和Bean的配置

    Spring IOC容器 和Bean的配置 : IOC和DI IOC(Inversion of Control):反转控制 在应用程序中的组件需要获取资源时,传统的方式是组件主动的从容器中获取所需要的 ...

  5. 三万字盘点Spring/Boot的那些常用扩展点

    Spring对于每个Java后端程序员来说肯定不陌生,日常开发和面试必备的.本文就来盘点Spring/SpringBoot常见的扩展点,同时也来看看常见的开源框架是如何基于这些扩展点跟Spring/S ...

  6. 盘点Spring/Boot的那些常用扩展点

    Spring对于每个Java后端程序员来说肯定不陌生,日常开发和面试必备的.本文就来盘点Spring/SpringBoot常见的扩展点,同时也来看看常见的开源框架是如何基于这些扩展点跟Spring/S ...

  7. Spring IoC容器以及Bean的创建过程

    1 Spring 静态结构介绍 什么是Spring,可以自己网上查询,总之,可以说是一个面向Web应用开发的,轻量级,企业级框架.它包含了如下图所示一些模块,这些模块的详细的概念和所负责的职责,可以通 ...

  8. [Spring实战系列](6)配置Spring IOC容器的Bean

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/SunnyYoona/article/details/50619900 1. 简介 Spring提供了 ...

  9. Spring IOC 容器根据Bean 名称或者类型进行autowiring 自动依赖注入

    //根据类型对属性进行自动依赖注入 protected void autowireByType(String beanName, AbstractBeanDefinition mbd, BeanWra ...

  10. spring一: 容器以及bean生命周期

    spring框架的几个优点: 1. 轻量级  2. 针对接口编程,解耦合   3. aop编程   4. 方便集成各种优秀框架  5.非侵入式   6.容器 IOC(Inversion of Cont ...

最新文章

  1. lua sleep函数实现
  2. codeforces732D Exams(二分)
  3. ASP.NET高质量生成缩略图
  4. Processing--鼠标响应(1)
  5. 790. Domino and Tromino Tiling
  6. python遍历获取一个类的所有子类
  7. AgileEAS.NET 4.0重构裁剪,新的ORM、支持Linq,正式支持WPF,开放更多的接口
  8. 开源硬件基金是如何运作的_如何在没有任何风险投资资金的情况下通过开源硬件赚钱
  9. 高性能Web动画和渲染原理系列(3)——transform和opacity为什么高性能
  10. GridView控件RowDataBound事件中获取列字段的几种途径
  11. Flex builder3 序列号生成器
  12. RT-Thread : IEEE1588/PTP 协议的实现(2)
  13. mysql既有整数又有小树字段类型,事业单位招考计算机专业知识试题
  14. IPA (苹果应用程序文件格式)
  15. stm32f103——基本定时器与定时器中断
  16. 互联网发展简史(1)ARPANET的建立
  17. [HAOI2008] 排名系统
  18. 借东风拉马力,龙头券商东方财富发展持续向好
  19. 怎样实现cmd命令窗口的快速复制粘贴操作
  20. SOA部署:反常道而行之

热门文章

  1. 扩增子测序引入的假阳性稀有类群干扰对微生物群落多样性、构建机制及相互作用的研究...
  2. C#微信开发---用户关注微信号后公众号发送欢迎关注
  3. 基于Php+MySql数据库架构的网络验证系统
  4. GeekBand-极客班-C++算法原理与实践-董飞-课程笔记(一)
  5. Django测试开发平台搭建
  6. 迪杰斯特拉(Dijkstra)算法
  7. 华为手机2.3亿出货量背后,一场技术+市场的胜利
  8. redis实战【西橙先生】
  9. 介绍几个免费的英文ASP.NET的CMS程序
  10. 【零基础学Python】Day8 Python基本数据类型之Dictionary