一、前置知识
1 后置处理器 - PostProcessor
- PostProcessor本身也是一种需要注册到容器里的Bean
- 其里面的方法会在特定的实际被容器调用
- 它能实现在不改变容器或者Bean核心逻辑的情况下对Bean进行扩展
- 例如:对Bean进行包装,影响其行为、修改Bean的内容甚至替换掉整个Bean等
PostProcessor的种类
- BeanDefinitionRegistryPostProcessor
- BeanFactoryPostProcessor
- BeanPostProcessor
1.1 BeanDefinitionRegistryPostProcessor
- BeanDefinitionRegistryPostProcessor,它继承了BeanFactoryPostProcessor
- 允许在正常的 BeanFactoryPostProcessor检测开始之前注册更多的自定义beandefinition
- 可以利用它扫描其它第三放工具类,将其注册进容器,实现框架的整合
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor { void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException; }
代码示例:往容器中多注册一个User类的BeanDefination
@Configuration
public class CustomizedBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
Class<?> clazz = User.class;
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
GenericBeanDefinition definition = (GenericBeanDefinition) builder.getRawBeanDefinition();
registry.registerBeanDefinition("user5", definition);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
}
1.2 BeanPostProcessor
- BeanPostProcessor
public interface BeanPostProcessor { //该方法在bean实例化完毕(且已经注入完毕),在afterPropertiesSet或自定义init方法执行之前 @Nullable default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } //在afterPropertiesSet或自定义init方法执行之后 @Nullable default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } }
代码示例:每个Bean在初始化前后都会调用
@Configuration
public class CustomizedBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException{
System.out.println(beanName + "调用了 postProcessBeforeInitialization() ");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException{
System.out.println(beanName + "调用了 postProcessAfterInitialization() ");
return bean;
}
}
2 Aware
- 从Bean中获取到容器实例并对其进行操作
代码示例:ApplicationContext、BeanNameAware
@Controller
public class WelcomeController implements ApplicationContextAware, BeanNameAware {
private String myName;
private ApplicationContext myContainer;
@Autowired
private WelcomeService welcomeService;
public void handleRequest(){
welcomeService.sayHello("来自Controller的问候");
System.out.println("我是谁:" + myName);
String[] beanDefinitionNames = myContainer.getBeanDefinitionNames();
for(String beanDefinitionName : beanDefinitionNames) {
System.out.println("召唤容器神兽,通过神兽获得:" + beanDefinitionName);
}
}
@Override
public void setBeanName(String name) {
this.myName = name;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.myContainer = applicationContext;
}
}
3 Spring事件驱动模型
3.1 回调函数
- 回调函数:往组件注册自定义的方法以便组件在特定场景下调用
- Runnable接口的run方法就是很好的回调函数例子
- 先让线程休眠2s,2s之后run()继续执行,这就是一种回调
Thread thread = new Thread(new Runnable() { @Override public void run() { System.out.println("我要休息啦"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("我被回调啦"); } }); thread.start();
3.2 事件监听器模式
- 监听器将监听自己感兴趣的时间,一旦时间发生,便做出响应
- 它有三个组件
- 事件源(Event Source):负责产生事件的对象。比如我们常见的按钮,按钮就是一个事件源,能够产生“点击”这个事件
- 事件监听器(Event Listener):负责处理事件的对象
- 事件对象(Event Object):或者称为事件对象,是事件源和事件监听器之间的信息桥梁。是整个事件模型驱动的核心
代码示例
-
创建事件对象
@Getter@Setter public class Event { private String type; }
-
创建事件监听器接口
public interface EventListener { public void processEvent(Event event); }
-
创建两个事件监听器接口的实现类
public class SingleClickEventListener implements EventListener { @Override public void processEvent(Event event) { if("singleclick".equals(event.getType())){ System.out.println("单击被触发了"); } } }
public class DoubleClickEventListener implements EventListener { @Override public void processEvent(Event event) { if("doubleclick".equals(event.getType())){ System.out.println("双击被触发了"); } } }
-
创建事件源
public class EventSource { private List<EventListener> listenerList = new ArrayList<>(); public void register(EventListener listener){ listenerList.add(listener); } public void publishEvent(Event event){ for(EventListener listener: listenerList){ listener.processEvent(event); } } }
-
测试
public static void main(String[] args) { EventSource eventSource = new EventSource(); SingleClickEventListener singleClickEventListener = new SingleClickEventListener(); DoubleClickEventListener doubleClickEventListener = new DoubleClickEventListener(); Event event = new Event(); event.setType("doubleclick"); eventSource.register(singleClickEventListener); eventSource.register(doubleClickEventListener); eventSource.publishEvent(event); }
3.3 Spring事件驱动模型
3.3.1 事件 - ApplicationEvent抽象类
- 可以通过ApplicationEvent中的source属性获得事件源
3.3.2 事件监听器 - ApplicationListener
- 可以自己实现ApplicationListener接口或者使用注解
@EventListener
实现监听器
3.3.3 事件发布器 - Publisher & Multicaster
-
ApplicationEventPublisher
只拥有发布事件的功能。ApplicationContext
继承了此接口,也就是说ApplicationContext拥有事件发布的能力- 可以看到ApplicationEventPublisher中只有两个和发布事件相关的方法
@FunctionalInterface public interface ApplicationEventPublisher { default void publishEvent(ApplicationEvent event) { publishEvent((Object) event); } void publishEvent(Object event); }
-
ApplicationEventMulticaster,拥有更丰富的功能,它除了拥有发布事件的方法之外还拥有添加和删除ApplicationListener的方法
public interface ApplicationEventMulticaster { }
-
我们可以通过ApplicationEventPublisherAware获取到ApplicationEventPublisher,也就是ApplicationContext,从而发布自定义事件给容器中注册的自定义的ApplicationListener去处理
ApplicationEventPublisher和ApplicationEventMulticaster之间的关系
- 如果Bean和容器本身只想发布事件,而不想维护事件本身,比如事件监听器等,于是Spring将抽象出事件发布器接口ApplicationEventPublisher,而ApplicationEventMulticaster则作为代理,让Multicaster实现Publisher里面的publishEvent()逻辑
二、Spring容器初始化逻辑
1 总体分析
-
以AnnotationConfigApplicationContext为例,它会执行AbstractApplicationContext的refresh()方法
@Override public void refresh() throws BeansException, IllegalStateException { // 给容器refresh加锁,避免容器处在refresh阶段时,容器进行了初始化或者销毁的操作 synchronized (this.startupShutdownMonitor) { // 调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识,具体方法 prepareRefresh(); //告诉子类启动refreshBeanFactory()方法,Bean定义资源文件的载入从 //子类的refreshBeanFactory()方法启动,里面有抽象方法 //针对xml配置,最终创建内部容器,该容器负责 Bean 的创建与管理,此步会进行BeanDefinition的注册 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 注册一些容器中需要的系统Bean.例如classloader,beanfactoryPostProcessor等 prepareBeanFactory(beanFactory); try { //允许容器的子类去注册postProcessor ,钩子方法 postProcessBeanFactory(beanFactory); // 激活在容器中注册为bean的BeanFactoryPostProcessors //对于注解容器,org.springframework.context.annotation.ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry //方法扫描应用中所有BeanDefinition并注册到容器之中 invokeBeanFactoryPostProcessors(beanFactory); // 注册拦截bean创建过程的BeanPostProcessor registerBeanPostProcessors(beanFactory); // 找到“messageSource”的Bean提供给ApplicationContext使用, // 使得ApplicationContext具有国际化能力。 initMessageSource(); // 初始化ApplicationEventMulticaster该类作为事件发布者, // 可以存储所有事件监听者信息,并根据不同的事件,通知不同的事件监听者。 initApplicationEventMulticaster(); // 预留给 AbstractApplicationContext 的子类用于初始化其他特殊的 bean, // 该方法需要在所有单例 bean 初始化之前调用 // 比如Web容器就会去初始化一些和主题展示相关的Bean(ThemeSource) onRefresh(); // 注册监听器(检查监听器的bean并注册它们) registerListeners(); //设置自定义的类型转化器ConversionService, // 设置自定义AOP相关的类LoadTimeWeaverAware, // 清除临时的ClassLoader // ,实例化所有的类(懒加载的类除外) finishBeanFactoryInitialization(beanFactory); // 初始化容器的生命周期事件处理器,(默认使用DefaultLifecycleProcessor),调用扩展了SmartLifecycle接口的start方法 // 当Spring容器加载所有bean并完成初始化之后,会接着回调实现该接口的类中对应的方法(start()方法) // 并发布容器刷新完毕事件ContextRefreshedEvent给对应的事件监听者 finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } // Destroy already created singletons to avoid dangling resources. //销毁已创建的Bean destroyBeans(); // Reset 'active' flag. //取消refresh操作,重置容器的同步标识 cancelRefresh(ex); // Propagate exception to caller. throw ex; } finally { // 重置Spring内核中的共用的缓存,因为我们可能再也不需要单例bean的元数据了…… resetCommonCaches(); } } }
2 prepareRefresh()
3 obtainFreshBeanFactory()
- 如果是AnnotationConfigApplicationContext,它实际调用的是GenericApplicationContext的refreshBeanFactory()方法
- DefaultListableBeanFactory在调用AnnotationConfigApplicationContext的时候就创建了
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { // 用的是GenericApplicationContext的refreshBeanFactory()方法 refreshBeanFactory(); // 返回 DefaultListableBeanFactory 实例 return getBeanFactory(); }
- 针对xml配置,最终创建内部容器,该容器负责 Bean 的创建与管理,此步会进行BeanDefinition的注册
4 prepareBeanFactory()
- 向内部容器中注册添加一些需要的系统Bean。例如classloader,beanfactoryPostProcessor等
- 这里的内部容器指的是DefaultListableBeanFactory
- 设置AnnotationConfigApplicationContext的类加载器实例,这样内部容器就能通过此类加载器去加载外部容器的资源
- 设置临时类加载器
// 设置临时类加载器 // 1.用于AbstractApplicationContext中的临时类型匹配 // 2.在进行AOP的时候会生成代理类,这些代理类是临时的,将临时的代理类放入临时的类加载器 beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
5 postProcessBeanFactory()
- 允许容器的子类去注册postProcessor ==> 钩子方法,子类可以实现也可以不实现
6 invokeBeanFactoryPostProcessors()
- 它会激活在容器中注册为bean的BeanFactoryPostProcessors
- 对于注解容器,最终会调用ConfigurationClassPostProcessor的
postProcessBeanDefinitionRegistry
,该方法扫描应用中所有BeanDefinition并注册到容器之中
- 对于注解容器,最终会调用ConfigurationClassPostProcessor的
7 registerBeanPostProcessors()
- 注册BeanPostProcessor
8 initMessageSource()
- 国际化配置,针对不同的地区展示不同的语言
9 initApplicationEventMulticaster()
- 初始化ApplicationEventMulticaster该类作为事件发布者, 可以存储所有事件监听者信息,并根据不同的事件,通知不同的事件监听者。
- 该方法会判断容器是否已经注册了ApplicationEventMulticaster, 如果容器存在ApplicationEventMulticaster的bean实例,则赋值给容器的applicationEventMulticaster;没有则新建 SimpleApplicationEventMulticaster,并完成 SimpleApplicationEventMulticaster Bean 的注册
- SimpleApplicationEventMulticaster既支持同步发布也支持异步发布
10 onRefresh()
- 该方法是一个钩子方法,是AbstractApplicationContext 预留其子类用于初始化其他特殊的 Bean,该方法需要在所有单例 Bean 初始化之前调用
- 比如Web容器就会去初始化一些和主题展示相关的Bean(ThemeSource)
11 registerListeners()
- 向前面创建的ApplicationEventMulticaster注册监听器(检查监听器的Bean并注册它们)
12 finishBeanFactoryInitialization()
- 在此方法中会实例化所有剩余的(非延时加载的)单例Bean
// 实例化所有剩余的(non-lazy-init非延时加载的)单例 beanFactory.preInstantiateSingletons();
- 调用的是 DefaultListableBeanFactory 的 preInstantiateSingletons() 方法
- 该方法中会遍历BeanDefinationNames,执行getBean()方法创建Bean
13 finishRefresh()
- 初始化容器的生命周期事件处理器,(默认使用DefaultLifecycleProcessor)
14 resetCommonCaches()
- 重置Spring内核中的共用的缓存