前言
Spring的核心思想之一就是IOC(控制反转),而IOC的实现方式DI(依赖注入),也就是说当某个bean需要依赖另一个bean时,就可以采用依赖注入的方式将依赖的bean自动注入到该bean中。但是如果一个bean依赖的对象并非是一个bean,此时通过容器的依赖注入显然就无法实现了,不过Spring容器提供了扩展接口,当某个bean对某个对象有兴趣或者是想要获取该对象时,比如想要获取Spring容器本身的资源,此时就可以采用Aware接口来获取。
一、Aware接口
Aware接口是Aware系列接口的顶级接口,当时Aware接口没有任何定义,仅仅是一个声明,也就是仅仅起到了一个标识的作用。实现了Aware接口的类就会被Spring容器所感知。而具体需要感知什么内容需要具体的子接口去定义。
比如说想要得到BeanFactory这个对象,此时就可以定义一个BeanFactoryAware接口实现Aware接口;想要得到ApplicationContext对象,就可以定义ApplicationContextAware接口,那么实现了对应接口的bean就可以获取到对应的对象。
每个Aware接口的子接口,内部都需要有一个set方法,将本身设置进去,这样实现了该接口的类就可以获取到该对象了
比如某个bean实现了BeanFactoryAware接口,BeanFactoryAware接口就会有一个setBeanFactroy(BeanFactroy beanFactory)方法,子类实现了之后,就可以得到beanFactory对象了。同理实现了XXXAware接口,就可以得到XXX这个对象。
二、Spring提供的常用的Aware接口
Spring提供了Aware接口的同时,也提供了很多自带的Aware子接口,主要是用于获取Spring容器本身的对象。如下图示:
可以看出Spring本身就已经提供了很多的Aware接口,需要使用到某个对象就可以实现对应的Aware接口即可
2.1、BeanFactoryAware接口(获取BeanFactory对象)
1 public interface BeanFactoryAware extends Aware { 2 3 /** 4 * 设置BeanFactory属性 5 */ 6 void setBeanFactory(BeanFactory beanFactory) throws BeansException; 7 8 }
2.2、ApplicatioContextAware接口(获取ApplicationContext对象)
public interface ApplicationContextAware extends Aware { /** * 设置ApplicationContext属性 */ void setApplicationContext(ApplicationContext applicationContext) throws BeansException; }
2.3、BeanNameAware接口(获取当前bean的beanName)
public interface BeanNameAware extends Aware { /** * 设置BeanName属性 */ void setBeanName(String name); }
2.4、ApplicationEventPublisherAware接口(获取容器中事件发布器,可以用于发布事件)
public interface ApplicationEventPublisherAware extends Aware { /** * 设置事件发布器属性 */ void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher); }
2.5、ResourceLoaderAware接口(获取资源加载器,用于获取外部资源文件)
public interface ResourceLoaderAware extends Aware { /** * 设置资源加载器属性 */ void setResourceLoader(ResourceLoader resourceLoader); }
接口比较多就不再一一列举,可以看出每个Aware子接口都有一个共同点,就是都有一个set方法用于设置该类型对象的方法。
三、Aware接口使用
以Spring提供的Aware接口为例,自定义Bean分别实现Spring提供的Aware接口,测试案例如下:
1 public class AwareBean implements BeanNameAware, BeanFactoryAware, ApplicationContextAware { 2 3 private String beanName; 4 5 private BeanFactory beanFactory; 6 7 private ApplicationContext applicationContext; 8 9 @Override 10 public void setBeanFactory(BeanFactory beanFactory) throws BeansException { 11 this.beanFactory = beanFactory; 12 } 13 14 @Override 15 public void setBeanName(String beanName) { 16 this.beanName = beanName; 17 } 18 19 @Override 20 public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 21 this.applicationContext = applicationContext; 22 } 23 24 public void test(){ 25 System.out.println("beanName:" + beanName); 26 System.out.println("从BeanFactory中获取当前bean " + beanFactory.getBean(AwareBean.class).equals(this)); 27 System.out.println("从ApplicationContext中获取当前bean " + applicationContext.getBean(AwareBean.class).equals(this)); 28 } 29 }
自定义AwareBean对象,分别实现了BeanNameAware、BeanFactoryAware和ApplicationContextAware接口,分别实现方法给内部属性赋值,调用test()方法测试结果如下:
1 beanName:awareBean 2 从BeanFactory中获取当前bean true 3 从ApplicationContext中获取当前bean true
既然bean可以通过实现BeanFactoryAware和ApplicationContextAware接口的方式可以注入Spring容器,所以bean获取其他bean的方式就可以通过容器直接获取,而不需要通过依赖注入来实现了,比如以下案例:
1 public class AwareBean implements ApplicationContextAware { 2 3 private ApplicationContext applicationContext; 4 5 private UserService userService; 6 private OrderService orderService; 7 8 @Override 9 public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 10 this.applicationContext = applicationContext; 11 this.orderService = applicationContext.getBean(OrderService.class); 12 this.userService = applicationContext.getBean(UserService.class); 13 } 14 15 public void test(){ 16 System.out.println(userService != null); 17 System.out.println(orderService != null); 18 } 19 }
AwareBean依赖UserService和OrderService,但是没有采用依赖注入的方式,而是直接通过从Spring容器ApplicationContext中获取来设置赋值。
四、Aware接口的实现原理解析
当bean实现了Aware接口之后,由于实现了Aware接口的方法,所以bean在初始化的过程中就需要执行Aware接口的方法,准确的说是在bean填充属性之后,执行init方法之前。
具体执行的逻辑是在初始化bean的方法initializeBean方法中,由前面几篇文章可知,bean的初始化过程分成 createBeanInstance(创建bean) ->populateBean(属性注入) ->initializeBean(执行初始化方法) 三步
而Aware接口方法的执行就是在第三步initializeBean方法当中,源码如下:
1 protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { 2 if (System.getSecurityManager() != null) { 3 AccessController.doPrivileged((PrivilegedAction<Object>) () -> { 4 /** 1、执行Aware接口的方法*/ 5 invokeAwareMethods(beanName, bean); 6 return null; 7 }, getAccessControlContext()); 8 } 9 else { 10 /** 1、执行Aware接口的方法*/ 11 invokeAwareMethods(beanName, bean); 12 } 13 14 Object wrappedBean = bean; 15 if (mbd == null || !mbd.isSynthetic()) {
/** 2、执行bean的前置处理器方法*/ 16 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); 17 } 18 19 try { 20 /** 3、执行初始化方法*/ 21 invokeInitMethods(beanName, wrappedBean, mbd); 22 } 23 catch (Throwable ex) { 24 throw new BeanCreationException( 25 (mbd != null ? mbd.getResourceDescription() : null), 26 beanName, "Invocation of init method failed", ex); 27 } 28 if (mbd == null || !mbd.isSynthetic()) {
/** 4、执行bean的后置处理器方法*/ 29 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); 30 } 31 32 return wrappedBean; 33 }
从源码中可看出bean的初始化方法中会先执行Aware接口的方法,然后才会去执行bean的具体的初始化方法。所以执行Aware接口的方法具体逻辑都在 invokeAwareMethods方法中实现,源码如下:
1 /** 执行 Aware接口的方法 */ 2 private void invokeAwareMethods(final String beanName, final Object bean) { 3 /**判断bean实现了Aware接口*/ 4 if (bean instanceof Aware) { 5 //1.如果实现了BeanNameAware接口,则执行setBeanName方法 6 if (bean instanceof BeanNameAware) { 7 ((BeanNameAware) bean).setBeanName(beanName); 8 } 9 //2.如果实现了BeanClassLoaderAware接口,则执行setBeanClassLoader方法 10 if (bean instanceof BeanClassLoaderAware) { 11 ClassLoader bcl = getBeanClassLoader(); 12 if (bcl != null) { 13 ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl); 14 } 15 } 16 //3.如果实现了BeanFactoryAware接口,则执行BeanFactoryAware接口方法 17 if (bean instanceof BeanFactoryAware) { 18 ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this); 19 } 20 } 21 }
可以看出这里分别判断bean是否实现了对应的Aware子接口,如果实现了Aware子接口,就将Bean转换成对应Aware子接口的对象,然后直接执行对应的set方法,将需要传入的参数传入即可。
但是这个方法很明显只判断了BeanNameAware、BeanClassLoaderAware、BeanFactoryAware三个Aware接口,而Spring容器中还有很多的Aware接口的方法在这里并没有执行,那么其他的接口比如ApplicationContextAware等接口又是何时执行的呢?
此时如果熟悉Spring的后置处理器的同学可能已经想到了,在bean初始化之前,会执行bean的后置处理器的方法,而其他的Aware接口就是通过后置处理器来执行的。
现在还是回到上面的initializeBean方法之后,在执行了BeanFactory的默认invokeAwareMethods方法之后,会先执行bean的前置处理器方法,然后执行invokeInitMethods方法执行初始化逻辑,最后再执行bean的后置处理器方法,执行bean的后置逻辑。
所以可以得知bean初始化时会分别执行前置处理器和后置处理器方法,而会执行Aware接口的处理器是ApplicationContextAwareProcesser,此处理器是在初始化ApplicationContext时加入的
执行ApplicationContext初始化方法时会执行refresh()方法,而refresh方法中第三步就是预处理BeanFactory方法prepareBeanFactory(beanFactory)方法,代码如下:
1 protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { 2 // Tell the internal bean factory to use the context's class loader etc. 3 beanFactory.setBeanClassLoader(getClassLoader()); 4 beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())); 5 beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment())); 6 7 /** 创建ApplicationContextAwareProcessor对象,加入到BeanFactory的处理器中*/ 8 beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); 9 beanFactory.ignoreDependencyInterface(EnvironmentAware.class); 10 beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class); 11 beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); 12 beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); 13 beanFactory.ignoreDependencyInterface(MessageSourceAware.class); 14 beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); 15 16 /** 剩下代码省略*/ 17 }
在预处理BeanFactory时,会初始化ApplicationContextAwareProcessor对象,调用BeanFactory的addBeanPostProcessor方法阿静该处理器加入到BeanFactory中。而在初始化bean的时候,会遍历BeanFactory中的所有BeanPostProcessor,依次执行前置和后置方法。所以这里执行Aware接口的方法就需要在ApplicationContextAwareProcessor中查看,该类的源码如下:
1 class ApplicationContextAwareProcessor implements BeanPostProcessor { 2 3 private final ConfigurableApplicationContext applicationContext; 4 5 private final StringValueResolver embeddedValueResolver; 6 7 8 /** 9 * Create a new ApplicationContextAwareProcessor for the given context. 10 */ 11 public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) { 12 this.applicationContext = applicationContext; 13 this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory()); 14 } 15 16 17 @Override 18 @Nullable 19 /** 在bean的初始化之前执行 */ 20 public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { 21 if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware || 22 bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware || 23 bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){ 24 return bean; 25 } 26 27 AccessControlContext acc = null; 28 29 if (System.getSecurityManager() != null) { 30 acc = this.applicationContext.getBeanFactory().getAccessControlContext(); 31 } 32 33 if (acc != null) { 34 AccessController.doPrivileged((PrivilegedAction<Object>) () -> { 35 /**执行Aware接口方法*/ 36 invokeAwareInterfaces(bean); 37 return null; 38 }, acc); 39 } 40 else { 41 /** 执行Aware接口方法 */ 42 invokeAwareInterfaces(bean); 43 } 44 45 return bean; 46 } 47 48 /** 回调执行各种类型Aware接口的方法*/ 49 private void invokeAwareInterfaces(Object bean) { 50 //1.执行EnvironmentAware接口方法 51 if (bean instanceof EnvironmentAware) { 52 ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment()); 53 } 54 //2.执行EmbeddeValueResolverAware接口方法 55 if (bean instanceof EmbeddedValueResolverAware) { 56 ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver); 57 } 58 //3.执行ResourceLoaderAware接口方法 59 if (bean instanceof ResourceLoaderAware) { 60 ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext); 61 } 62 //4.执行ApplicationEventPublisherAware接口方法 63 if (bean instanceof ApplicationEventPublisherAware) { 64 ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext); 65 } 66 //5.执行MessageSourceAware接口方法 67 if (bean instanceof MessageSourceAware) { 68 ((MessageSourceAware) bean).setMessageSource(this.applicationContext); 69 } 70 //6.执行ApplicationContextAware接口方法 71 if (bean instanceof ApplicationContextAware) { 72 ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext); 73 } 74 } 75 }
可以看出在ApplicationContextAwareProcessor中的执行Aware接口的逻辑和BeanFactory初始化bean时的invokeAwareMethods方法逻辑基本差不多,都是依次判断bean是否实现了Aware的各个子接口,实现了对应的接口就将bean转换成对应接口的对象,然后直接执行对应的set方法,而这一步是在invokeAwareMethods方法执行之后,bean的init方法执行之前操作的
总结:
1、bean在初始化方法initializeBean方法中执行逻辑为先执行invokeAwareMethods执行BeanFactory提供的Aware子接口
2、然后遍历执行BeanFactory的后置处理器方法,其中ApplicationContextAwareProcessor处理器会执行ApplicationContext提供的Aware子接口方法
3、执行完Aware子接口方法之后,才会继续执行bean的初始化方法