Spring - aware注入原理

Spring中Aware接口原理


    在Spring中存在一个Aware接口,实现该接口可以让我们的Bean获取到Spring容器中特定的资源,但该接口只是个标记接口,不存在任何方法,因此我们还需要继承Aware来做特定资源获取的实现。

    换句话说:只要实现了Aware子接口的Bean都能获取到一个Spring底层组件。

    从我们熟悉的 refresh() 方法入手, 接下来调用的 prepareBeanFactory() 方法,会添加一些默认的后置处理器,这里我们关注的是添加ApplicationContextAwareProcessor实例。 

    一、注册时机

    ApplicationContextAwareProcessor的注册时机,即准备BeanFactory的时候,注册的入口在AbstractApplicationContext#prepareBeanFactory方法中。

    1. refresh

    AbstractApplicationContext#refresh

 1 public void refresh() throws BeansException, IllegalStateException {
 2         synchronized(this.startupShutdownMonitor) {
 3             StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
 4             this.prepareRefres);
 5             ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
 6             this.prepareBeanFactory(beanFactory);
 7 
 8             //...
 9 
10         }
11 } 

    2. prepareBeanFactory()

    AbstractApplicationContext#prepareBeanFactory

 1     protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
 2         beanFactory.setBeanClassLoader(this.getClassLoader());
 3         if (!shouldIgnoreSpel) {
 4             beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
 5         }
 6 
 7         beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, this.getEnvironment()));
 8         beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
 9         
10         //...
11 
12     }

    二、执行逻辑

    1. postProcessBeforeInitialization 

    1)判断是否是xxxAware接口,判断是,则继续往下

    2)通过invokeAwareInterfaces里面进行注入

    ApplicationContextAwareProcessor#postProcessBeforeInitialization 源码如下:

 1 @Nullable
 2 public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
 3     // 判断是否是xxxAware接口,判断是,则继续往下
 4     if (!(bean instanceof EnvironmentAware) && !(bean instanceof EmbeddedValueResolverAware) && !(bean instanceof ResourceLoaderAware) && !(bean instanceof ApplicationEventPublisherAware) && !(bean instanceof MessageSourceAware) && !(bean instanceof ApplicationContextAware) && !(bean instanceof ApplicationStartupAware)) {
 5         return bean;
 6     } else {
 7         AccessControlContext acc = null;
 8         if (System.getSecurityManager() != null) {
 9             acc = this.applicationContext.getBeanFactory().getAccessControlContext();
10         }
11 
12         if (acc != null) {
13             AccessController.doPrivileged(() -> {
14                 this.invokeAwareInterfaces(bean);
15                 return null;
16             }, acc);
17         } else {
18             // 在这个方法进行相应的注入
19             this.invokeAwareInterfaces(bean);
20         }
21 
22         return bean;
23     }
24 }

    2. invokeAwareInterfaces

    1)判断是否是xxxAware接口

    2) 如果是xxxAware接口,则获取xxx,调用setxxx方法进行注入

    ApplicationContextAwareProcessor#invokeAwareInterfaces 源码如下:

 1  private void invokeAwareInterfaces(Object bean) {
 2         if (bean instanceof Aware) {
 3             if (bean instanceof EnvironmentAware) {
 4                 ((EnvironmentAware)bean).setEnvironment(this.applicationContext.getEnvironment());
 5             }
 6 
 7             if (bean instanceof EmbeddedValueResolverAware) {
 8                 ((EmbeddedValueResolverAware)bean).setEmbeddedValueResolver(this.embeddedValueResolver);
 9             }
10 
11             if (bean instanceof ResourceLoaderAware) {
12                 ((ResourceLoaderAware)bean).setResourceLoader(this.applicationContext);
13             }
14 
15             if (bean instanceof ApplicationEventPublisherAware) {
16                 ((ApplicationEventPublisherAware)bean).setApplicationEventPublisher(this.applicationContext);
17             }
18 
19             if (bean instanceof MessageSourceAware) {
20                 ((MessageSourceAware)bean).setMessageSource(this.applicationContext);
21             }
22 
23             if (bean instanceof ApplicationContextAware) {
24                 ((ApplicationContextAware)bean).setApplicationContext(this.applicationContext);
25             }
26         }
27 
28     }

    三、执行时机

    ApplicationContextAwareProcessor本身并不是扩展点,而是实现了BeanPostProcessor,并实现postProcessBeforeInitialization(),所以并不需要去实现它,但是其内部包含了以下7个接口实现的执行时机,这几个接口的功能作用分别是:

    1. EnvironmentAware

    用于获取Enviroment,Enviroment可以获得系统内的所有参数;另外也可以通过注入的方式来获得Environment,用哪种方式需要以实现场景而决定。

    2. EmbeddedValueResolverAware

    用于获取StringValueResolver,StringValueResolver可以获取基于String类型的properties的变量;另外还可以使用@Value的方式来获取properties的变量,用哪种方式需要以实现场景而决定。 

    3. ResourceLoaderAware

    用于获取ResourceLoader,ResourceLoader可以用于获取classpath内所有的资源对象。

    4. ApplicationEventPublisherAware

    用于获取ApplicationEventPublisher,ApplicationEventPublisher可以用来发布事件,当然这个对象也可以通过spring注入的方式来获得,具体的实现方式可以参考Springboot事件监听机制的实战应用。

    5. MessageSourceAware

    用于获取MessageSource,MessageSource主要用来做国际化。

    6. ApplicationStartupAware

    Spring Boot 应用启动过程中进行额外的配置、监控或自定义操作。

    7. ApplicationContextAware

    用来获取ApplicationContext,ApplicationContext就是Spring上下文管理器。

    四、Aware调用链路

    1. 调用AbstractAutowireCapableBeanFactory的doCreateBean()方法

    2. 调用AbstractAutowireCapableBeanFactory的initializeBean()方法,代码如下: 

 1     protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
 2         if (System.getSecurityManager() != null) {
 3             AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
 4                 invokeAwareMethods(beanName, bean);
 5                 return null;
 6             }, getAccessControlContext());
 7         }
 8         else {
 9             invokeAwareMethods(beanName, bean);
10         }
11 
12         Object wrappedBean = bean;
13         if (mbd == null || !mbd.isSynthetic()) {
14             wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
15         }
16 
17         try {
18             invokeInitMethods(beanName, wrappedBean, mbd);
19         }
20         catch (Throwable ex) {
21             throw new BeanCreationException(
22                     (mbd != null ? mbd.getResourceDescription() : null),
23                     beanName, "Invocation of init method failed", ex);
24         }
25         if (mbd == null || !mbd.isSynthetic()) {
26             wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
27         }
28 
29         return wrappedBean;
30     }

    3. 调用AbstractAutowireCapableBeanFactory的applyBeanPostProcessorsBeforeInitialization()方法

    4. 调用ApplicationContextAwareProcessor的postProcessBeforeInitialization()方法

    5. 调用ApplicationContextAwareProcessor的invokeAwareInterfaces()方法

    6. 调用Aware接口实现的方法

    五、自定义aware

    自定义组件时,想要使用spring容器底层的一些组件,比如ApplicationContext、Beanfactory,xxx等,只需要让自定义组件实现xxxAware,在对象实例化的时候,会把spring底层的一些组件注入到自定义的bean中。

    举个例子:

 1 import org.springframework.beans.factory.BeanFactoryUtils;
 2 import org.springframework.context.ApplicationContext;
 3 import org.springframework.context.ApplicationContextAware;
 4 
 5 import java.util.Map;
 6 
 7 /**
 8  * 通过Spring上下文获取bean工具类
 9  *
10  * @author test
11  */
12 public class SpringContextUtils implements ApplicationContextAware {
13 
14     /**
15      * Spring应用上下文环境
16      */
17     private static ApplicationContext applicationContext;
18 
19     @Override
20     public void setApplicationContext(ApplicationContext applicationContext) {
21         SpringContextUtils.initSpringContext(applicationContext);
22     }
23 
24     public static ApplicationContext getApplicationContext() {
25         return applicationContext;
26     }
27 
28     @SuppressWarnings("unchecked")
29     public static <T> T getBean(String name) {
30         return (T) applicationContext.getBean(name);
31     }
32 
33     public static <T> T getBean(Class<T> clazz) {
34         return applicationContext.getBean(clazz);
35     }
36 
37     public static boolean isSingleton(String name) {
38         return applicationContext.isSingleton(name);
39     }
40 
41     /**
42      * 根据class对象返回IOC容器中其对象和其子类的对象。
43      * 未找到则返回空MAP。
44      * KEY为BEAN ID或者NAME,VALUE为BEAN实例
45      *
46      * @param type 需要找的bean类型的CLASS对象
47      * @return bean映射
48      */
49     public static <T> Map<String, T> getBeansByType(Class<T> type) {
50         return BeanFactoryUtils.beansOfTypeIncludingAncestors(SpringContextUtils.getApplicationContext(), type);
51     }
52 
53     /**
54      * 初始化ApplicationContext
55      *
56      * @param applicationContext 上下文
57      */
58     public static void initSpringContext(ApplicationContext applicationContext) {
59         SpringContextUtils.applicationContext = applicationContext;
60     }
61 
62     /**
63      * 获取业务线(业务线配置在配置文件中)
64      *
65      * @return 业务线
66      */
67     public static String getProjectBusinessLine() {
68         if (applicationContext == null) {
69             throw new RuntimeException("spring初始化失败");
70         }
71         return applicationContext.getEnvironment().getProperty("***.application.businessLine");
72     }
73 
74     /**
75      * 获取项目名称(项目名称配置在配置文件中)
76      *
77      * @return 项目名称
78      */
79     public static String getProjectName() {
80         if (applicationContext == null) {
81             throw new RuntimeException("spring初始化失败");
82         }
83         return applicationContext.getEnvironment().getProperty("***.application.name");
84     }
85 }

 

posted @ 2024-08-13 16:00  欢乐豆123  阅读(7)  评论(0编辑  收藏  举报