Bean 的实例化之 @Autowired、@Value
├─finishBeanFactoryInitialization(beanFactory); Spring 核心方法中的
│ ├─beanFactory.preInstantiateSingletons();
│ │ ├─getBean(beanName);
│ │ │ ├─doGetBean(name, null, null, false);
│ │ │ │ ├─这里完成了对所有 MergedBeanDefinitionPostProcessor 实现类的调用。
│ │ │ │ ├─如:CommonAnnotationBeanPostProcessor(@PostConstruct、@PreDestroy、@Resource)
│ │ │ │ ├─如:AutowiredAnnotationBeanPostProcessor(@Autowired, @Value)
│ │ │ │ ├─applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
│ │ │ │ │ ├─processor.postProcessMergedBeanDefinition(mbd, beanType, beanName);
AutowiredAnnotationBeanPostProcessor
AutowiredAnnotationBeanPostProcessor 支持了@Autowired, @Value 等注解的扫描解析工作。
- 收集注解 @Autowired @Value
- 完成 @Autowired 的依赖注入(因为实现了 InstantiationAwareBeanPostProcessor)。
- 支持的注解类型可以在构造函数或者 Static 静态块中找。收集过程基本上跟 @Resource 注解的收集差不多。
- doCreateBean 时,寻找当前正在实例化的 bean 中有 @Autowired 注解的构造函数。然后把有有 @Autowired 注解的构造函数返回。
- 不管是 Field、Method、还是构造函数中有@Autowired 注解引入的类,都是通过 getBean 方法进行实例化获取 bean 的实例的。
java
public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor,
MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
public AutowiredAnnotationBeanPostProcessor() {
this.autowiredAnnotationTypes.add(Autowired.class);
this.autowiredAnnotationTypes.add(Value.class);
try {
this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
}
自动注入 bean 到 Map 集合
java
package com.github.mengweijin.mybatisplus.demo.autowiredmap.bean;
public interface Apple {
void execute();
}
@Slf4j
@Component(BigApple.BEAN_NAME)
public class BigApple implements Apple {
public static final String BEAN_NAME = "bigApple";
@Override
public void execute() {
log.debug("execute {}", this.getClass().getSimpleName());
}
}
@Slf4j
@Component(SmallApple.BEAN_NAME)
public class SmallApple implements Apple {
public static final String BEAN_NAME = "smallApple";
@Override
public void execute() {
log.debug("execute {}", this.getClass().getSimpleName());
}
}
java
package com.github.mengweijin.mybatisplus.demo.autowiredmap;
import com.github.mengweijin.mybatisplus.demo.autowiredmap.bean.Apple;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Map;
@Slf4j
@Service
public class AppleService {
/**
* Spring 会自动注入所有实现了 Apple 接口的 bean 到这个 appleBeanMap 中,其中 key 为 spring bean 的 name.
*/
@Autowired
private Map<String, Apple> appleMap;
/**
* 执行所有实现类的方法
*/
public void executeAll() {
appleMap.forEach((beanName, apple) -> apple.execute());
}
/**
* 根据类型调用不同的实现类方法
*
* @param beanName
*/
public void execute(String beanName) {
appleMap.get(beanName).execute();
}
}
测试
java
package com.github.mengweijin.mybatisplus.demo.autowiredmap;
import com.github.mengweijin.mybatisplus.demo.autowiredmap.bean.BigApple;
import com.github.mengweijin.mybatisplus.demo.autowiredmap.bean.SmallApple;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
@Slf4j
public class AutowiredMapTest {
@Test
public void test() {
String basePackages = "com.github.mengweijin.mybatisplus.demo.autowiredmap";
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(basePackages);
AppleService bean = context.getBean(AppleService.class);
log.debug("******************************************************");
// 执行全部实现类
bean.executeAll();
log.debug("******************************************************");
// 根据类型调用不同的实现类方法
bean.execute(BigApple.BEAN_NAME);
bean.execute(SmallApple.BEAN_NAME);
log.debug("******************************************************");
context.close();
}
}