aware 英文译为:意识到的
一 .XXXAware在spring里表示对XXX感知,实现XXXAware接口,并通过实现对应的set-XXX方法,然后就可以使用XXX了。------容器感知
二. Spring提供的Aware接口
接口 | 解释 |
---|---|
BeanNameAware | 获得到容器中Bean的名称 |
BeanFactoryAware | 获得当前bean factory,这样可以调用容器的服务 |
ApplicationContextAware | 获得当前application context,这样可以调用容器的服务 |
EnvironmentAware | 将上下文中Enviroment注入进去,一般获取配置属性可以使用 |
MessageSourceAware | 获得message source这样可以获得文本信息 |
ApplicationEventPublisherAware | 应用事件发布器,可以发布事件 |
ResourceLoaderAware | 获得资源加载器,可以获得外部资源文件 |
BeanClassLoaderAware | 会将加载当前Bean的ClassLoader注入进去 |
三.基本原理
aware 接口的调用分为两部分
一部分是容器初始化的时候会进行一部分aware接口的set
下面是源码部分
package org.springframework.context.support;
class ApplicationContextAwareProcessor implements BeanPostProcessor {
//...
//这里就是容器自动调用set方法的地方,其实就是调用自定义的类实现的setApplicationContext方法,这样类就获取到了applicationContext
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初始化的时候
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
四. 实例
Spring自动调用。并且会在Spring自身完成Bean配置之后,且在调用任何Bean生命周期回调(初始化或者销毁)方法之前就调用这个方法。换言之,在程序中使用BeanFactory.getBean(String beanName)之前,Bean的名字就已经设定好了。
@Component
public class UserService implements BeanNameAware, BeanFactoryAware {
private BeanFactory beanFactory;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
public String getMyBeanName() {
BeanName beanName = beanFactory.getBean(BeanName.class);
System.out.println(beanFactory.isSingleton("customBeanName"));
return beanName.getBeanName();
}
private String beanName;
@Override
public void setBeanName(String beanName) {
System.out.println("UserService beanName : " + beanName);
this.beanName = beanName;
}
}
2.BeanFactoryAware
作用:获取创建bean的工厂,可以通过工厂去进行一些操作
这个方法可能是在根据某个配置文件创建了一个新工厂之后,Spring才调用这个方法,并把BeanFactory注入到Bean中。
让bean获取配置自己的工厂之后,当然可以在Bean中使用这个工厂的getBean()方法,但是,实际上非常不推荐这样做,因为结果是进一步加大Bean与Spring的耦合,而且,能通过DI注入进来的尽量通过DI来注入。
当然,除了查找bean,BeanFactory可以提供大量其他的功能,例如销毁singleton模式的Bean。
factory.preInstantiateSingletons();方法。preInstantiateSingletons()方法立即实例化所有的Bean实例,有必要对这个方法和Spring加载bean的机制做个简单说明。
方法本身的目的是让Spring立即处理工厂中所有Bean的定义,并且将这些Bean全部实例化。因为Spring默认实例化Bean的情况下,采用的是lazy机制,换言之,如果不通过getBean()方法(BeanFactory或者ApplicationContext的方法)获取Bean的话,那么为了节省内存将不实例话Bean,只有在Bean被调用的时候才实例化他们。
代码如上
3.ApplicationContextAware
作用:这个接口用的比较广泛,通常用来获取bean,也可以发布事件,需要applicationListener配合,当然既然拿到了容器,容器内的东西都可以拿到。
代码如下
@Component
public class ApplicationUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
/**
* 通过name获取 Bean.
* @param name
* @return
*/
public static Object getBean(String name){
return applicationContext.getBean(name);
}
public static <T>T getBean(String id,Class<T> type){
return applicationContext.getBean(id,type);
}
}
四. EnvironmentAware
作用:在SpringBoot中的应用
凡注册到Spring容器内的bean,实现了EnvironmentAware接口重写setEnvironment方法后,在工程启动时可以获得application.properties的配置文件配置的属性值。
新建一个application.properties,放在resource下或者下面的config里
project.name= myproject
比较常见SpirngBoot整合Mybatis应用,通过environment给数据库赋值。
/**
* *
* @ClassName MyProjectc.java
* @author 沉鱼
* @date 2017年11月28日 下午4:35:39
*/
@Configuration
public class MyProjectc implements EnvironmentAware {
@Override
public void setEnvironment(Environment environment) {
String projectName = environment.getProperty("project.name");// 键值对
System.out.println(projectName);
}
}
五.MessageSourceAware
作用:这个接口是为了国际化
基础教程:https://geek-docs.com/spring/spring-tutorials/messagesource.html
//MessageSourceAware(ApplicationContextAware)接口
public class ExtendBean implements MessageSourceAware {
@Override
public void setMessageSource(MessageSource messageSource) {
this.setterMs = messageSource;
}
}
六.ApplicationEventPublisherAware(ApplicationContextAware)
顺便带上ApplicationListener 扩展,代码如下
作用:获取发布事件的接口,ApplicationContext也可以,
// 自定义事件
public class TestEvent extends ApplicationEvent {
private static final long serialVersionUID = 5331762369790483076L;
public TestEvent(Object source) {
super(source);
}
}
@Component
public class MyApplicationListener implements ApplicationListener<TestEvent> {
@Override
public void onApplicationEvent(TestEvent event) {
System.out.println("reveive:"+event);
}
}
public static void main(String[] args) {
// ApplicationContextAware
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
// 这里的applicationContext,也可以换成实现接口ApplicationEventPublisherAware的方式发布事件
applicationContext.publishEvent(new TestEvent("TestEvent"));
System.out.println(applicationContext.getBean(User.class));
applicationContext.close();
// new AnnotationConfigApplicationContext();
}
七.ResourceLoaderAware
作用:通过实现ResourceLoaderAware重写setResourceLoader获取资源文件的加载接口
Resource resource =
resourceLoader.getResource(“classpath:org/light4j/sping4/senior/aware/test.txt”);
loader.getResource(“application.properties”);
八.BeanClassLoaderAware
作用:获取加载当前bean的类加载器。
[1]聊聊国际化MessageSource