构造器位置的自动装配
@Autowired 注解支持添加到: 构造器、参数、方法、属性上.
默认注入到 IOC 容器中的组件,容器启动会调用无参构造创建对象,再进行赋值操作,当我们注入对象时,可以写一个有参构造器,加上@Autowired,实现对象的自动注入.
/**
* @author Demon-HY
* @date 2019-12-12
*/
@Service
public class UserService {
private final UserDao userDao;
// 1. 当前对象如果只有一个有参构造器,可以省略 @Autowired 注解
// 2. @Autowired 可以直接加在参数上: public UserService(@Autowired UserDao userDao)
@Autowired
public UserService(UserDao userDao) {
this.userDao = userDao;
}
@Override
public String toString() {
return "UserService{" +
"userDao=" + userDao +
'}';
}
}
方法位置的自动装配
在配置类中注入@Bean时,实现注入
/**
* @author Demon-HY
* @date 2019-12-12
*/
public class UserService {
private final UserDao userDao;
public UserService(UserDao userDao) {
this.userDao = userDao;
}
@Override
public String toString() {
return "UserService{" +
"userDao=" + userDao +
'}';
}
}
/**
* @author Demon-HY
* @date 2019-12-24
*/
@Configuration
@ComponentScan(value = "com.demon")
public class ConfigOfAutowired {
// @Bean 标注的方法创建对象时,方法参数的值从容器中获取,
// 所以这里的UserDao 可以添加 @Autowired, 也可以不添加,他都会从容器中查询
@Bean
public UserService userService(UserDao userDao) {
return new UserService(userDao);
}
}
实现Aware注入Spring底层组件
Spring 给我们提供了一些可以注入Spring 底层组件的类,具体有哪些可以看一下 Aware 接口的实现类.
比较常见的有:
- ApplicationContextAware: Spring 上下文
- EnvironmentAware: Spring 环境变量
- BeanName: 对象名
- EmbeddedValueResolverAware: 解析String中的占位符
编写一个测试类:
package com.demon;
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.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.util.StringValueResolver;
/**
* @author Demon-HY
* @date 2020-1-8
*/
@Service
public class TestAware implements ApplicationContextAware, BeanNameAware, EmbeddedValueResolverAware, EnvironmentAware {
private ApplicationContext applicationContext;
private String beanName;
private StringValueResolver resolver;
private Environment environment;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@Override
public void setBeanName(String name) {
this.beanName = name;
System.out.println("对象名: " + name);
}
@Override
public void setEmbeddedValueResolver(StringValueResolver resolver) {
this.resolver = resolver;
format();
}
// 测试 StringValueResolver
private void format() {
System.out.println(this.resolver.resolveStringValue("当前系统版本: ${os.name}"));
}
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
System.out.println("获取系统设置: " + environment.getProperty("os.name"));
}
@Override
public String toString() {
return "TestAware{" +
"applicationContext=" + applicationContext +
", beanName='" + beanName + '\'' +
", resolver=" + resolver +
'}';
}
}
写一个测试类看下效果:
/**
* @author Demon-HY
* @date 2019-12-9
*/
public class IOCTestAutowired {
@Test
public void test() throws Exception {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigOfAutowired.class);
TestAware testAware = context.getBean(TestAware.class);
}
}
# 打印
对象名: testAware
获取系统设置: Windows 7
当前系统Windows 7
每一个Aware都有一个对应的后置处理器去完成赋值操作,比如 ApplicationContextAwareProcessor, 这些后置处理器命名一般为: XXXProcessor.
Aware 接口实现原理
我们在上面例子的 setEnvironment() 方法里面打一个断点,这样可以看到完整的调用栈,可以看到下面这段代码:
// AbstractAutowireCapableBeanFactory.initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd);
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
// 判断是否有当前类的访问权限
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
// 创建 bean实例
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// TODO 这里就是对 bean 实例中实现的那些Aware接口设置属性值的方法
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 给 bean 的属性赋值
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
看名字就知道,这个方法是Bean实例初始化方法, 里面的 applyBeanPostProcessorsBeforeInitialization() 方法就是对 bean 实例中实现的那些Aware接口设置属性值的方法,继续看这个方法的实现:
// AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName);
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
// getBeanPostProcessors() 方法获取了所有Spring支持的后置处理器
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
// TODO 循环遍历调用后置处理器方法
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
上面这个方法只是获取了所有的后置处理器,并循环去调用,检查bean有没有需要处理的数据,继续看postProcessBeforeInitialization()方法:
// ApplicationContextAwareProcessor.postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException;
@Override
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
AccessControlContext acc = null;
// 检查 bean 操作权限
if (System.getSecurityManager() != null &&
(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
if (acc != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
invokeAwareInterfaces(bean);
return null;
}
}, acc);
}
else {
// TODO 这里就是实际调用后置处理器设置bean属性的方法
invokeAwareInterfaces(bean);
}
return bean;
}
看到这里就知道了,Spring会去判断 bean 有没有实现对应的接口
继续看 invokeAwareInterfaces() 方法:
// ApplicationContextAwareProcessor.invokeAwareInterfaces(Object bean);
private void invokeAwareInterfaces(Object bean) {
// 判断 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);
}
}
}
看到上面的代码,也就很清楚的知道Spring 目前支持的Aware都有哪些了.
咖啡小馆
QQ群:
823971061
点击按钮入群