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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值