Spring在进行自动装配时,除了使用常用的注解进行装配之外,如果需要在自定义组件中注入Spring的一些底层组件,例如:BeanFactory,ApplicationContext等,则可以利用Spring提供的一系列Aware接口来完成自动注入。
温馨提示:本博客已经发布小程序,可在微信小程序中搜索”百变码农”,手机上也能看!
1、使用示例
例如给Pen组件中注入Spring的上下文ApplicationContext,并且在Pen组件中获取当前Bean的名称,如下:
a.配置类AutowiredConfig:
/** * Created by wangbin33 on 2020/3/8. */ @Configuration @ComponentScan({"com.wb.spring.autowired"}) public class AutowiredConfig { }
b.Pen类:
/** * Created by wangbin33 on 2020/3/8. */ @Component public class Pen implements ApplicationContextAware,BeanNameAware { /** 保存Spring容器的引用,如果在本类中其他地方使用,可以直接用 */ private ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { System.out.println("当前IOC容器对象为:"+applicationContext); this.applicationContext = applicationContext; } @Override public void setBeanName(String name) { System.out.println("当前Bean的名称为:" + name); } }
c.测试类TestMain1:
/** * Created by wangbin33 on 2020/3/8. */ public class TestMain1 { public static void main(String[] args) { ApplicationContext acx = new AnnotationConfigApplicationContext(AutowiredConfig.class); System.out.println(acx); } }
运行结果:
当前Bean的名称为:pen 当前IOC容器对象为:org.springframework.context.annotation.AnnotationConfigApplicationContext@3d646c37, started on Sun Mar 08 15:27:35 CST 2020 org.springframework.context.annotation.AnnotationConfigApplicationContext@3d646c37, started on Sun Mar 08 15:27:35 CST 2020
可以看到,在Pen类中已经获取到了ApplicationContext容器对象和当前bean的名称。
2、底层原理举例解析
在Spring中Aware接口作为一个顶层接口,其底层的xxxAware子接口中全部定义了setxxxAware方法,用于交给具体的类来实现,然后通过xxxAwareProcessor来实现具体的注入。
例如:ApplicationContextAwarePostProcessor源码执行流程如下:
class ApplicationContextAwareProcessor implements BeanPostProcessor { private final ConfigurableApplicationContext applicationContext; private final StringValueResolver embeddedValueResolver; /** * Create a new ApplicationContextAwareProcessor for the given context. */ public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) { // 创建Processort的时候,完成applicationContext的赋值 this.applicationContext = applicationContext; // 创建默认的值解析器,用来解析classpath中配置的占位符变量的值 this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory()); } // 该方法在创建Bean的过程中,在Bean初始化方法执行完成之后会被调用 @Override @Nullable public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException { AccessControlContext acc = null; // 获取bean工厂中的AccessControlContext,默认为null if (System.getSecurityManager() != null && (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware || bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware || bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) { acc = this.applicationContext.getBeanFactory().getAccessControlContext(); } // 由于acc为null,默认该方法不会执行 if (acc != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareInterfaces(bean); return null; }, acc); } else { // 调用Aware接口的方法 invokeAwareInterfaces(bean); } return bean; } // 调用Aware方法 private void invokeAwareInterfaces(Object bean) { if (bean instanceof Aware) { if (bean instanceof EnvironmentAware) { ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment()); } if (bean instanceof EmbeddedValueResolverAware) { ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver); } if (bean instanceof ResourceLoaderAware) { ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext); } if (bean instanceof ApplicationEventPublisherAware) { ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext); } if (bean instanceof MessageSourceAware) { ((MessageSourceAware) bean).setMessageSource(this.applicationContext); } // 判断到当前的Bean为ApplicationContextAware的实现类 if (bean instanceof ApplicationContextAware) { // 将Bean向上转型为ApplicationContextAware,并回调其 // setApplicationContext方法,然后将ioc对象作为参数传入 // 在Pen子类中就可以接收到传入的ApplicationContext对象了 ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext); } } } // 创建Bean的过程中,执行完初始化方法之后,接着会被调用. @Override public Object postProcessAfterInitialization(Object bean, String beanName) { return bean; } }
其他的Aware接口都有对应的Processort后置处理器,用来处理对应的组件注入。
3、Spring中常用的Aware接口及作用
(1)BeanFactoryAware:可以获取用于创建Bean的工厂;
(2)BeanNameAware:获取当前bean的名称;
(3)ApplicationContextAware:获取当前Bean所在的Spring应用上下文对象,利用该对象可以获取到Spring容器中Bean的很多信息,例如:所有bean的名称,所有bean的定义,bean注册中心等等;
(4)MessageSourceAware:用于获取当前应用的国际化信息,包括区域,语言等,在做web应用的国际化时使用;
(5)EnvironmentAware:用于获取当前Bean运行的环境信息,例如:操作系统,环境变量,当前classpath中配置的所有property属性值及属性名称等。
注意:上述接口都有对应的Bean的后置处理器,用来完成对应的组件注入功能,名称为xxxAwareProcessor。具体的实现逻辑和ApplicationContextAwareProcessor类似,感兴趣可以自己先阅读相关代码实现,后期会持续更新文章详细介绍Spring各个功能的底层源码实现。
至此,Spring中通过Aware接口注入底层组件的内容介绍完毕!欢迎转发文章!
温馨提示:如果小程序端代码显示混乱,是因为移动端兼容性导致,可移步至PC端站点查看!
文章属于原创,如果转发请标注文章来源:个人小站【www.jinnianshizhunian.vip】
另外提供一些优秀的Java架构师及IT开发视频,书籍资料。无需注册,无需登录即可下载,免费下载地址:https://www.592xuexi.com