Spring注解驱动开发——Aware接口

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/rubulai/article/details/80543728

Spring的Aware接口:在Spring中有个Aware接口

public interface Aware {

}

Spring中很多接口继承于该接口,该接口的子接口可以为Spring容器中的组件提供Spring自带的一些组件,比如ApplicationContext、BeanFactory等,只需要实现XxxAware接口即可,比如容器中的组件通过实现ApplicationContextAware接口来获取ApplicationContext对象

public interface ApplicationContextAware extends Aware {
	void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
@Component
public class ContextBean implements ApplicationContextAware{
	
	private ApplicationContext context;

	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.context = applicationContext;
	}

}

组件Bean仅仅是实现了接口,接口中有个setXxx(Xxx xxx)的方法,组件Bean实现的接口并不会为相应的Xxx赋值,那么这些值是怎么注入到组件Bean中的呢?是Spring通过回调的方式注入的,也就是说Spring在发现组件Bean实现了XxxAware接口时,会调用其setXxx(Xxx xxx)方法将xxx(ApplicationContext、BeanFactory等)注入到相应的组件bean中

常用的Aware子接口:BeanNameAware(查找当前bean的名字)、ApplicationContextAware(获取当前IOC容器)、BeanFactoryAware(获取beanFactory)、EmbeddedValueResolverAware(Spring内置的值解析器,可以解析出占位符、SpEL表达式等)

@Component
public class ContextBean implements EmbeddedValueResolverAware {

	private StringValueResolver resolver;

	public void setEmbeddedValueResolver(StringValueResolver resolver) {
		String resolveStringValue = resolver.resolveStringValue("你好:${os.name},我今年#{2*15}岁了");
		System.out.println(resolveStringValue);//你好:Windows 10,我今年30岁了
		this.resolver = resolver;
	}
}

通过${}获取系统环境变量,#{}则可以动态计算一些值

之所以能通过实现ApplicationContextAware等接口的方式获取到ApplicationContext等Spring的底层组件,是因为一些Bean的后置处理器在起作用,比如ApplicationContextAwareProcessor,在这些bean的后置处理器中会回调容器组件bean中的setXxx(Xxx xxx)方法将相应的Spring组件注入,每个XxxAware都有对应的XxxAwareProcessor后置处理器,这些后置处理器会在创建完bean之后再为bean的属性赋值或者注入相应的组件,具体是怎么实现的呢?看ApplicationContextAwareProcessor类的代码:

public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
	AccessControlContext acc = 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();
	}

	if (acc != null) {
		AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
			invokeAwareInterfaces(bean);
			return null;
		}, acc);
	}
	else {
		invokeAwareInterfaces(bean);
	}

	return bean;
}

在前置方法中会判断bean是否是XxxAware的子类,然后调用invokeAwareInterfaces(bean)方法,正是在该方法中注入的这些底层组件:

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);
		}
		if (bean instanceof ApplicationContextAware) {
			((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
		}
	}
}

该方法中会判断bean具体实现了哪些Aware接口,然后会回调该bean的setXxx(Xxx xxx)方法将xxx注入到bean中,这就是Aware注入的原理 

猜你喜欢

转载自blog.csdn.net/rubulai/article/details/80543728