1.概述
自定义的组件要想使用Spring容器底层的一些组件,比如ApplicationContext(IOC容器)、底层的BeanFactory等等,那么只需要让自定义组件实现XxxAware接口即可。此时,Spring在创建对象的时候,会调用XxxAware接口中定义的方法注入相关的组件
2.XxxAware接口概览
在Spring中,类似于ApplicationContextAware接口的设计有很多,本质上,Spring中形如XxxAware这样的接口都继承了Aware接口,我们来看下Aware接口的源码,如下所示:
package org.springframework.beans.factory;public interface Aware {}
Aware接口是Spring 3.1版本中引入的接口,在Aware接口中,并未定义任何方法
3.XxxAware接口案例
3.1.ApplicationContextAware接口
通过ApplicationContextAware接口我们可以获取到IOC容器
创建一个Red类,实现ApplicationContextAware接口,并在实现的setApplicationContext()方法中将ApplicationContext输出,如下所示:
package com.tianxia.springannotation.entity;import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;/*** 红色类* @author liqb* @date 2023-04-23 15:43**/
@Component
public class Red implements ApplicationContextAware{private ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {System.out.println("传入的IOC:" + applicationContext);this.applicationContext = applicationContext;}
}
3.2.BeanNameAware接口
通过BeanNameAware接口获取到当前bean在Spring容器中的名称,如下所示:
package com.tianxia.springannotation.entity;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.stereotype.Component;/*** 红色类* @author liqb* @date 2023-04-23 15:43**/
@Component
public class Red implements ApplicationContextAware, BeanNameAware {private ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {System.out.println("传入的IOC:" + applicationContext);this.applicationContext = applicationContext;}@Overridepublic void setBeanName(String name) {System.out.println("当前bean的名字:" + name);}
}
3.3.EmbeddedValueResolverAware
通过EmbeddedValueResolverAware接口能够获取到String值解析器,如下所示:
package com.tianxia.springannotation.entity;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.stereotype.Component;
import org.springframework.util.StringValueResolver;/*** 红色类* @author liqb* @date 2023-04-23 15:43**/
@Component
public class Red implements ApplicationContextAware, BeanNameAware, EmbeddedValueResolverAware {private ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {System.out.println("传入的IOC:" + applicationContext);this.applicationContext = applicationContext;}@Overridepublic void setBeanName(String name) {System.out.println("当前bean的名字:" + name);}@Overridepublic void setEmbeddedValueResolver(StringValueResolver resolver) {String resolveStringValue = resolver.resolveStringValue("你好,${os.name},我的年龄是#{20*18}");System.out.println("解析的字符串:" + resolveStringValue);}
}
StringValueResolver会解析那些String类型的值的,如果这个String类型的值里面有一些占位符,那么也会把这些占位符给解析出来,最后返回一个解析后的值
运行测试方法,输出的结果信息如下所示:
/*** 测试方法* @author liqb* @date 2023-05-08 11:51*/
@Test
public void test03() {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAutowired.class);Color color = (Color) applicationContext.getBean("color02");System.out.println(color);applicationContext.close();
}
3.XxxAware原理
XxxAware接口的底层原理是由XxxAwareProcessor实现类实现的,也就是说每一个XxxAware接口都有它自己对应的XxxAwareProcessor实现类。 例如,ApplicationContextAware接口的底层原理就是由ApplicationContextAwareProcessor类实现的。从ApplicationContextAwareProcessor类的源码可以看出,其实现了BeanPostProcessor接口,本质上是一个后置处理器。
class ApplicationContextAwareProcessor implements BeanPostProcessor {private final ConfigurableApplicationContext applicationContext;private final StringValueResolver embeddedValueResolver;
}
分析ApplicationContextAware接口的原理为例,看看Spring是怎么将ApplicationContext对象注入到Red类中的
在Red类的setApplicationContext()方法上打一个断点,并运行测试方法,如下所示:
ApplicationContext对象已经注入到Red类的setApplicationContext()方法中了
然后定位到了postProcessBeforeInitialization()方法
postProcessBeforeInitialization()方法所在的类就是ApplicationContextAwareProcessor,在postProcessBeforeInitialization()方法中调用的invokeAwareInterfaces()方法,如下所示
Red类实现了ApplicationContextAware接口后,Spring为啥会将ApplicationContext对象自动注入到setApplicationContext()方法中就是如此