浅析对Spring aware接口理解

2022-10-07,,,,

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方法时的处理逻辑。

《浅析对Spring aware接口理解.doc》

下载本文的Word格式文档,以方便收藏与打印。