1. aware接口的作用
通过aware接口可以获取spring容器相关信息,但这样会与spring容器耦合。
2. 常用aware接口及作用
执行顺序从上到下。
类名 | 作用 |
---|---|
beannameaware | 获得容器中bean名称 |
beanclassloaderaware | 获得类加载器 |
beanfactoryaware | 获得bean创建工厂 |
environmentaware | 获得环境变量 |
embeddedvalueresolveraware | 获取spring容器加载的properties文件属性值 |
resourceloaderaware | 获得资源加载器 |
applicationeventpublisheraware | 获得应用事件发布器 |
messagesourceaware | 获得文本信息 |
applicationcontextaware | 获得当前应用上下文 |
3. 使用样例:applicationcontextaware 在bean中获取上下文
/** * 获取spring注入对象方法 */ @component("springutil") public final class springutil implements applicationcontextaware { /** * 应用上下文 */ private static applicationcontext applicationcontext; /** * public方法可能被调用,导致线程不安全。这样写也是为了通过sonar检测 * @param applicationcontext 通过aware设置上下文 */ @override public void setapplicationcontext(@nonnull applicationcontext applicationcontext) { synchronized (springutil.class) { if (null == springutil.applicationcontext) { springutil.applicationcontext = applicationcontext; } } } /** * 获取注入对象 * * @param name 对象名称 * @return 指定注入对象 */ public static object getbean(string name) { return getapplicationcontext().getbean(name); } private static applicationcontext getapplicationcontext() { return applicationcontext; } /** * 获取注入对象 * * @param clazz 对象类型 * @param <t> 泛型 * @return 指定注入对象 */ public static <t> t getbean(class<t> clazz) { return getapplicationcontext().getbean(clazz); } /** * 获取注入对象 * * @param name 对象名称 * @param clazz 对象类型 * @param <t> 泛型 * @return 指定注入对象 */ public static <t> t getbean(string name, class<t> clazz) { return getapplicationcontext().getbean(name, clazz); } }
4. 自定义aware的方式
先定义一个继承aware的接口,然后注册一个实现beanpostprocessor接口的bean,在postprocessbeforeinitialization中处理aware接口的逻辑。
举一个例子。获取调用自定义aware接口方法的时间。
4.1 定义继承aware的接口
public interface timeaware extends aware { void settriggertime(date date); }
4.2 注册实现beanpostprocessor接口的bean
@component public class awarepostprocessor implements beanpostprocessor { private final configurableapplicationcontext applicationcontext; /** * 可写可不写,这个构造是为了获取applicationcontext */ public awarepostprocessor(configurableapplicationcontext applicationcontext) { this.applicationcontext = applicationcontext; } @override public object postprocessbeforeinitialization(object bean, string beanname) throws beansexception { if (bean instanceof aware) { if (bean instanceof timeaware) { // 实现自定义aware接口的逻辑,设置调用的时间 ((timeaware)bean).settriggertime(new date()); } } return bean; } }
4.3 实现timeaware接口,并测试
@import(awarepostprocessor.class) public class test implements timeaware { date date; @override public void settriggertime(date date) { this.date = date; } public static void main(string[] args) { applicationcontext context = new annotationconfigapplicationcontext(test.class); test bean = context.getbean(test.class); system.out.println(bean.date); } }
结果:
5. 源码处理方式
- bean实例化->填充属性->初始化,在初始化阶段将实现aware接口的bean的方法执行。
1.先执行实现了下面三个aware接口的方法
- beannameaware
- beanclassloaderaware
- beanfactoryaware
2.调用初始化方法
3.执行实现剩下aware接口的方法
5.1 初始化阶段的源码逻辑
abstractautowirecapablebeanfactory#initializebean
protected object initializebean(string beanname, object bean, @nullable rootbeandefinition mbd) { if (system.getsecuritymanager() != null) { accesscontroller.doprivileged((privilegedaction<object>) () -> { invokeawaremethods(beanname, bean); return null; }, getaccesscontrolcontext()); } else { /** * 调用bean实现的aware接口的方法,主要包括下面三个接口 * beannameaware ----> setbeanname() * beanclassloaderaware ----> setbeanclassloader() * beanfactoryaware ----> setbeanfactory() */ invokeawaremethods(beanname, bean); } object wrappedbean = bean; if (mbd == null || !mbd.issynthetic()) { /** 调用bean对象的postprocessbeforeinitialization方法,此处会执行标注@postconstruct注解的方法 */ // 此处会调用applicationcontextawareprocessor执行其他的aware方法. wrappedbean = applybeanpostprocessorsbeforeinitialization(wrappedbean, beanname); } try { /** * 执行bean的初始化方法: * * 1.先判断bean是否实现了initializingbean接口,如果实现了initializingbean接口,则调用bean对象的afterpropertiesset方法; * 2.然后判断bean是否有指定init-method方法,如果指定了init-method方法,则调用bean对象的init-method指定的方法. */ invokeinitmethods(beanname, wrappedbean, mbd); } catch (throwable ex) { throw new beancreationexception( (mbd != null ? mbd.getresourcedescription() : null), beanname, "invocation of init method failed", ex); } if (mbd == null || !mbd.issynthetic()) { /** * 调用bean对象的postprocessafterinitialization方法 * * 如果需要创建代理,在该步骤中执行postprocessafterinitialization方法的时候会去创建代理 * 调用abstractautoproxycreator类的postprocessafterinitialization方法,然后调用wrapifnecessary方法去创建代理. * * * 另外还有一些aware接口,也会在该步骤中执行,例如:applicationcontextawareprocessor后置处理器,对应的setapplicationcontext方法会被执行. */ wrappedbean = applybeanpostprocessorsafterinitialization(wrappedbean, beanname); } return wrappedbean; }
5.2 实现前三个aware接口的处理
调用initializebean =>invokeawaremethods方法将前三个aware方法调用
abstractautowirecapablebeanfactory#invokeawaremethods
private void invokeawaremethods(string beanname, object bean) { if (bean instanceof aware) { if (bean instanceof beannameaware) { ((beannameaware) bean).setbeanname(beanname); } if (bean instanceof beanclassloaderaware) { classloader bcl = getbeanclassloader(); if (bcl != null) { ((beanclassloaderaware) bean).setbeanclassloader(bcl); } } if (bean instanceof beanfactoryaware) { ((beanfactoryaware) bean).setbeanfactory(abstractautowirecapablebeanfactory.this); } } }
5.3 剩余实现aware接口的bean的处理
调用initializebean =>applybeanpostprocessorsbeforeinitialization=>beanpostprocessor.postprocessbeforeinitialization
进入applicationcontextawareprocessor#postprocessbeforeinitialization=>invokeawareinterfaces
private void invokeawareinterfaces(object bean) { 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); } if (bean instanceof applicationcontextaware) { ((applicationcontextaware) bean).setapplicationcontext(this.applicationcontext); } }
因此可以自定义aware接口,并且注册一个实现beanpostprocessor的postprocessbeforeinitialization方法的bean,处理调用aware方法时的处理逻辑。