Spring系列(六)——Spring扩展原理

案例准备

创建项目spring-extension

  • pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.ittzg</groupId>
    <artifactId>spring-extension</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <priject.build.sourceEncoding>UTF-8</priject.build.sourceEncoding>
        <maven.complier.source>1.8</maven.complier.source>
        <maven.complier.target>1.8</maven.complier.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.1.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>
</project>
  • 项目结构
一、BeanFactoryPostProcessor
  1. 源码
@FunctionalInterface
public interface BeanFactoryPostProcessor {

	/**
	 * Modify the application context's internal bean factory after its standard
	 * initialization. All bean definitions will have been loaded, but no beans
	 * will have been instantiated yet. This allows for overriding or adding
	 * properties even to eager-initializing beans.
	 * @param beanFactory the bean factory used by the application context
	 * @throws org.springframework.beans.BeansException in case of errors
	 */
    //在该类初始化之后,更新应用容器中的bean工厂;此时所有bean的定义信息将被加载,但是却没有实例化的;
    //它将允许bean的属性值被修改,也可提前初始化bean
    //注意:实现改接口的类@Value的属性注入将会失效
	void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}
  1. 案例
=================================User.java===============================
@Component
public class User {
    public User() {
        System.out.println("--------User-----初始化--------");
    }
}
===================MyBeanFactoryPostProcessor.java======================
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Value("zhangsan")
    private String name;
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        System.out.println("---------MyBeanFactoryPostProcessor--postProcessBeanFactory---");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
=============================ConfigBean.java==========================
@Configuration
@ComponentScan(value = "com.ittzg.bean")
public class ConfigBean {
}
=========================MainTest.java================================
public class MainTest {
    public static void main(String[] args) {
          AnnotationConfigApplicationContext annotationConfigApplicationContext =
                new AnnotationConfigApplicationContext(ConfigBean.class);
        MyBeanFactoryPostProcessor myBeanFactoryPostProcessor = annotationConfigApplicationContext.getBean(MyBeanFactoryPostProcessor.class); System.out.println("myBeanFactoryPostProcessor:name="+myBeanFactoryPostProcessor.getName());
        annotationConfigApplicationContext.close();
    }
}
=========================输出结果================================
---------MyBeanFactoryPostProcessor--postProcessBeanFactory---
--------User-----初始化--------
myBeanFactoryPostProcessor:name=null
二、BeanDefinitionRegistryPostProcessor
  1. 实现该接口的bean的方法执行时间将在实现BeanFactoryPostProcessor的bean的方法执行之前
  2. 案例
==============MyBeanDefinitionRegistryPostProcessor.java=================
@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        System.out.println("---------MyBeanDefinitionRegistryPostProcessor--postProcessBeanDefinitionRegistry---");
    }

    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        System.out.println("---------MyBeanDefinitionRegistryPostProcessor--postProcessBeanFactory---");
    }
}

=========================输出结果================================
---------MyBeanDefinitionRegistryPostProcessor--postProcessBeanDefinitionRegistry---
---------MyBeanDefinitionRegistryPostProcessor--postProcessBeanFactory---
---------MyBeanFactoryPostProcessor--postProcessBeanFactory---
--------User-----初始化--------
myBeanFactoryPostProcessor:name=null
  1. 源码解析实现BeanDefinitionRegistryPostProcessor的bean的方法为什么会在实现BeanFactoryPostProcessor的bean的方法执行之前
  • AnnotationConfigApplicationContext的创建时需要调用构造
  • debug获取方法调用栈
  • 有上述方法调用栈,我们可以得出BeanDefinitionRegistryPostProcessor的调用时机是在执行invokeBeanFactoryPostProcessors:286, PostProcessorRegistrationDelegate (org.springframework.context.support)该方法的时候发生的我们接下来查看源码
  • 由于方法内容较多我们截取需要的片段
  • 有上述可知实现BeanDefinitionRegistryPostProcessor的bean的方法为什么会在实现BeanFactoryPostProcessor的bean的方法执行之前
三、ApplicationListener
  1. 源码
//函数式接口
//容器的事件的监听
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
	void onApplicationEvent(E event);
}
  1. 案例
public class MyApplicationListener implements ApplicationListener {

    public void onApplicationEvent(ApplicationEvent applicationEvent) {
        System.out.println("收到事件:"+applicationEvent);
    }
}
=====输出
---------MyBeanDefinitionRegistryPostProcessor--postProcessBeanDefinitionRegistry---
---------MyBeanDefinitionRegistryPostProcessor--postProcessBeanFactory---
---------MyBeanFactoryPostProcessor--postProcessBeanFactory---
--------User-----初始化--------
收到事件:org.springframework.context.event.ContextRefreshedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@300ffa5d, started on Fri May 17 00:15:48 GMT+08:00 2019]
myBeanFactoryPostProcessor:name=null
收到事件:org.springframework.context.event.ContextClosedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@300ffa5d, started on Fri May 17 00:15:48 GMT+08:00 2019]
  1. ApplicationListener执行源码分析 方法调用栈
  • 执行流程
    • 创建容器
    • 调用refresh()刷新容器,在该方法中调用finishRefresh()
    • publishEvent()给容器注册事件
    • multicastEvent调用多博器执行invokeListener方法,完成ApplicationListener.onApplicationEvent()方法的执行
四、 @EventListener
  • @EventListener的功能和完成ApplicationListener的功能相同使用方法如下
@Service
public class UserService {

    public UserService() {
        System.out.println("--------UserService-----初始化--------");
    }

    @EventListener(value = {ApplicationEvent.class})
    public void listenEvent(ApplicationEvent event){
       System.out.println("收到事件:"+event);
   }
}
=======
---------MyBeanDefinitionRegistryPostProcessor--postProcessBeanDefinitionRegistry---
---------MyBeanDefinitionRegistryPostProcessor--postProcessBeanFactory---
---------MyBeanFactoryPostProcessor--postProcessBeanFactory---
--------User-----初始化--------
--------UserService-----初始化--------
收到事件:org.springframework.context.event.ContextRefreshedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@300ffa5d, started on Fri May 17 00:30:07 GMT+08:00 2019]
myBeanFactoryPostProcessor:name=null
收到事件:org.springframework.context.event.ContextClosedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@300ffa5d, started on Fri May 17 00:30:07 GMT+08:00 2019]

转载于:https://my.oschina.net/ittzg/blog/3050613

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值