Aware接口的功能就是,一个类只要实现这个类接口的相关子类,则可以拿到相应的东西。
上面到底可以拿到什么东西呢,我们来看下 它的实现类
举个例子,比如我定义一个类ErwanAware并且实现了ApplicationContextAware这个接口,通过重写它的相关方法,就可以拿到ApplicationContext,这个东西其实就是ioc容器
定义一个类ErwanAware2这个类实现了EnvironmentAware,通过重写EnvironmentAware的相关方法,就可以拿到Environment,这个东西就环境变量相关。
定义一个类实现多个接口,我就可以拿到多个东西,接下来我们直接上代码
创建配置类
@Configuration
@ComponentScan("com.erwan.cap11.bean")
public class Cap11MainConfig {
}
新建一个light类并且实现 多个接口:ApplicationContextAware, BeanNameAware, BeanFactoryAware, EnvironmentAware, EmbeddedValueResolverAware
@Component
public class Light
implements ApplicationContextAware, BeanNameAware, BeanFactoryAware, EnvironmentAware, EmbeddedValueResolverAware {
public Light() {
System.out.println("light的构造函数" + this);
}
public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException {
System.out.println("通过ApplicationContext 得到的是:" + applicationContext);
}
public void setBeanFactory(final BeanFactory beanFactory) throws BeansException {
System.out.println("通过beanFactory得到的light" + beanFactory.getBean("light"));
}
public void setBeanName(final String name) {
System.out.println("通过beanName获得的name:" + name);
}
public void setEmbeddedValueResolver(final StringValueResolver resolver) {
String str = resolver.resolveStringValue("3+4=#{3+4},当前系统:${os.name}");
System.out.println(str);
}
public void setEnvironment(final Environment environment) {
String oSname = environment.getProperty("os.name");
System.out.println("环境变量得到的一个属性:" + oSname);
}
}
新建测试类
@Test
public void cap11() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Cap11MainConfig.class);
System.out.println(context);
}
测试结果如下:
light的构造函数com.erwan.cap11.bean.Light@36804139
通过beanName获得的name:light
通过beanFactory得到的lightcom.erwan.cap11.bean.Light@36804139
环境变量得到的一个属性:Windows 10
3+4=7,当前系统:Windows 10
通过ApplicationContext 得到的是:org.springframework.context.annotation.AnnotationConfigApplicationContext@17d0685f: startup date [Fri Aug 16 16:32:15 CST 2019]; root of context hierarchy
org.springframework.context.annotation.AnnotationConfigApplicationContext@17d0685f: startup date [Fri Aug 16 16:32:15 CST 2019]; root of context hierarchy
可以看到 实现了ApplicationContextAware可以拿到容器,结果和测试类new出来的容器是同一个
实现了 beanNameAware可以拿到当前实现类light的name
实现了beanFactoryAware可以拿到beanFactory,beanFactory就是创建报错bean的工厂,通过beanFactory可以得到任意的bean
实现了EnvironmentAware可以拿到环境变量Environment,环境变量可以拿到很多东西,比如当前操作系统,classpath下的配置文件
实现了EmbeddedValueResolverAware可以拿到一个表达式解析的工具类,可以操作它解析表达式。
总结:一个类实现了Aware 这个类接口的相关子类,则可以拿到相应的东西。
有人也许会问,为什么实现了Aware这个类就可以拿到对应的东西。
实现原理可以大致简略的解释为一下
ioc在启动的时候,会写个for循环,遍历Aware,然后调用具体方法
具体在 ParserStrategyUtils 类中,invokeAwareMethods这个方法,其他篇章会解释如何执行到这里的
public static void invokeAwareMethods(Object parserStrategyBean, Environment environment,
ResourceLoader resourceLoader, BeanDefinitionRegistry registry) {
if (parserStrategyBean instanceof Aware) {
if (parserStrategyBean instanceof BeanClassLoaderAware) {
ClassLoader classLoader = (registry instanceof ConfigurableBeanFactory ?
((ConfigurableBeanFactory) registry).getBeanClassLoader() : resourceLoader.getClassLoader());
if (classLoader != null) {
((BeanClassLoaderAware) parserStrategyBean).setBeanClassLoader(classLoader);
}
}
if (parserStrategyBean instanceof BeanFactoryAware && registry instanceof BeanFactory) {
((BeanFactoryAware) parserStrategyBean).setBeanFactory((BeanFactory) registry);
}
if (parserStrategyBean instanceof EnvironmentAware) {
((EnvironmentAware) parserStrategyBean).setEnvironment(environment);
}
if (parserStrategyBean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) parserStrategyBean).setResourceLoader(resourceLoader);
}
}
}
}