spring功能扩展之Aware接口

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);
    }
  }
}

四. 实例

  1. BeanNameAware
    作用:通过重写setBeanName ,获取BeanFactory中bean 的name或者id

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

你可能感兴趣的:(spring,java,spring)