零 前期准备
0 FBI WARNING
文章异常啰嗦且绕弯。
1 版本
spring版本 : spring 5.1.2.RELEASE
IDE : idea 2018.3
2 Bean Demo
package ioc;
/**
* java bean
*/
public class Person {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
3 Config Demo
package ioc;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 配置类
*/
@Configuration
public class IocConfig {
/**
* 用代码配置方式注入一个bean
*/
@Bean(name = "person")
public Person getPerson(){
Person person = new Person();
person.setAge(100);
person.setName("张三");
return person;
}
}
4 main方法
package ioc;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class IocTest {
public static void main(String[] args){
ApplicationContext context = new AnnotationConfigApplicationContext(IocConfig.class);
Person person = (Person) context.getBean("person");
System.out.println(person.getName() + " , " + person.getAge());
}
}
一 项目的启动和Bean的注入
1 总览
Spring 的初始化被封装在这行代码中:
ApplicationContext context = new AnnotationConfigApplicationContext(IocConfig.class);
这个构造器方法内部有三行代码:
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
this(); // 2 无参构造器
register(annotatedClasses); // 3 reader 注册配置类
refresh(); // 4 在 bean factory 中创造 bean
}
2 无参构造器
该 part 的起点为 AnnotationConfigApplicationContext 调用自身的无参构造器:
//AnnotationConfigApplicationContext.class
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
this(); // 2 无参构造器
register(annotatedClasses);
refresh();
}
追踪无参构造器:
//AnnotationConfigApplicationContext.class
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this); //2.1
this.scanner = new ClassPathBeanDefinitionScanner(this); //2.5
}
AnnotatedBeanDefinitionReader 创建的过程中会将 Spring 自身需要的 bean 和配置用的 bean 注册到 bean factory 中。
【ClassPathBeanDefinitionScanner 本例中暂时用不到,不做详细分析,只简单看一下构造方法】
AnnotationConfigApplicationContext 的父类 GenericApplicationContext 会在无参构造器中创建一个 DefaultListableBeanFactory ,也就是本例中的 bean factory:
//GenericApplicationContext.class
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
DefaultListableBeanFactory 内部会维护了多个 ConcurrentHashMap 对象,用于分门别类地保存 bean。
最主要的一个 map 对象是 singletonObjects。这个对象被定义在 DefaultSingletonBeanRegistry 中,用于存放所有的单例 bean:
//DefaultSingletonBeanRegistry.class
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
2.1
AnnotatedBeanDefinitionReader 创建的过程中将 spring 需要的几个 processor bean 注册到 DefaultListableBeanFactory 中。主要过程为:
//AnnotatedBeanDefinitionReader.class
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
//调用自身的另一个有参构造器
//此处的 registry 即为 AnnotationConfigApplicationContext 本身
//此处的 getOrCreateEnvironment(registry) 最终返回一个调用 StandardEnvironment 无参构造器创建出来的对象
this(registry, getOrCreateEnvironment(registry));
}
//AnnotatedBeanDefinitionReader.class
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
//参数非空效验
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
Assert.notNull(environment, "Environment must not be null");
//保存 AnnotationConfigApplicationContext
this.registry = registry;
//创建一个用于注解解析器,后面会用到
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
//注册 Spring 需要用到的 processor bean
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
Environment 顾名思义,即为 Spring 所处的环境,包括 properties 配置的读取等。本例中暂时没有用到,按下不表。
上述代码的核心是调用 AnnotationConfigUtils 的 registerAnnotationConfigProcessors(…) 方法,继续追踪:
//AnnotationConfigUtils.class
public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
registerAnnotationConfigProcessors(registry, null);
}
//AnnotationConfigUtils.class
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) {
//获取 bean factory
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
//以下代码设置了 beanFactory 的两个内部对象,暂时不展开
if (beanFactory != null) {
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
//新建一个集合,用于在方法末尾返回所有注册的 bean 的包装类,但是实际上本例中没有接收返回值,所以可以忽略
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
//判断 bean factory 中是否存在这个名称的 bean,如果不存在就注册一个,以下雷同
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
//将要注册的 processor class 包装成一个 BeanDefinition
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
//本例中 source 为 null
def.setSource(source);
//注册 bean,并添加到集合中
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
//jsr250Present 与 jpaPresent 均为 boolean 类型的变量
//jsr250Present 的意思是检查是否对 JSR-250 标准进行支持,jpaPresent 的意思是检查是否对 JPA 标准进行支持
//目前 Spring 支持 JSR-250 标准,不支持 JPA 标准
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition();
try {
def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
AnnotationConfigUtils.class.getClassLoader()));
}catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
}
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
}
//返回上述的集合
return beanDefs;
}
该方法中主体代码都是雷同的,即为:
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
//将要注册的 processor class 包装成一个 BeanDefinition
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
//本例中 source 为 null
def.setSource(source);
//注册 bean ,并添加到集合中
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME : org.springframework.context.annotation.internalConfigurationAnnotationProcessor
CONFIGURATION_BEAN_NAME_GENERATOR : org.springframework.context.annotation.internalConfigurationBeanNameGenerator
AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME : org.springframework.context.annotation.internalAutowiredAnnotationProcessor
COMMON_ANNOTATION_PROCESSOR_BEAN_NAME : org.springframework.context.annotation.internalCommonAnnotationProcessor
PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME : org.springframework.context.annotation.internalPersistenceAnnotationProcessor
PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME : org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor
EVENT_LISTENER_PROCESSOR_BEAN_NAME : org.springframework.context.event.internalEventListenerProcessor
EVENT_LISTENER_FACTORY_BEAN_NAME : org.springframework.context.event.internalEventListenerFactory
这些常量都是 spring 中类的路径和名称。
registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)
此行代码会通过 AnnotationConfigApplicationContext 调用到 DefaultListableBeanFactory 内部的 beanDefinitionMap 对象,最终查询到这个 bean 对象是否已经被注册。如果不存在,则执行下方的注册操作。
beanDefinitionMap 是 DefaultListableBeanFactory 内部存放所有已经注册了的 bean 的信息的 ConcurrentHashMap 对象,后面会经常提到。
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
RootBeanDefinition 是 BeanDefinition 的实现类。BeanDefinition 是 Spring 中 bean 的描述包装接口,用于保存 bean 的各类信息,包括且不限于 bean 的名称、父类、注解、是否惰性加载等属性。
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
BeanDefinitionHolder 是 BeanDefinition 的支持类,内部存储了 BeanDefinition 、bean name 、bean aliases(别名)。
【在 Spring 的 bean 注册过程中,有多次 BeanDefinition 和 BeanDefinitionHolder 的包装和解包装操作,具体有待学习】
registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)
起主要作用的是上面这行代码。追踪这个方法的实现:
//AnnotationConfigUtils.class
private static BeanDefinitionHolder registerPostProcessor(
BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
//bean 的角色定义
//BeanDefinition.ROLE_INFRASTRUCTURE = 2
definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
//调用 AnnotationConfigApplicationContext 的 registerBeanDefinition 方法
registry.registerBeanDefinition(beanName, definition);
//返回一个封装类
return new BeanDefinitionHolder(definition, beanName);
}
BeanDefinition 的 role 是指该 bean 在 Spring 中的角色定义。对于 Spring 注册进去的 processor bean,定义值均为 2,意思是 infrastructure(基础设施)。
除此以外角色定义还有 application(应用) 和 support(支持)。
AnnotationConfigApplicationContext 内部其实没有 registerBeanDefinition(…) 这个方法,而是继承自 GenericApplicationContext:
//GenericApplicationContext.class
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
//2.2
this.beanFactory.registerBeanDefinition(beanName, beanDefinition);
}
此方法实际上调用了 DefaultListableBeanFactory 的 registerBeanDefinition(…) 方法进行 bean 的注册。
2.2
继续追踪方法的内部实现:
//DefaultListableBeanFactory.class
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
//参数非空验证
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
//bean 的有效性验证
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
//beanDefinitionMap 为存储所有注册 bean 信息的 map 对象
//正常情况下此处获取的应该是 null 值,即该 bean 的信息还未注册
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
//如果 bean 已经存在于 map 中,则需要判断是否允许重写 bean definition
if (!isAllowBeanDefinitionOverriding()) { //不允许,抛出异常
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}else if (existingDefinition.getRole() < beanDefinition.getRole()) {
if (logger.isInfoEnabled()) {
logger.info("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
existingDefinition + "] with [" + beanDefinition + "]");
}
}else if (!beanDefinition.equals(existingDefinition)) {
if (logger.isDebugEnabled()) {
logger.debug("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}else {
if (logger.isTraceEnabled()) {
logger.trace("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
//只要设置为允许重写,就会在最后更新 map,只是记录的 log 内容会不同
this.beanDefinitionMap.put(beanName, beanDefinition);
}else { //正常情况下
if (hasBeanCreationStarted()) { //2.3
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}else {
//将 bean 注册入 beanDefinitionMap 中
this.beanDefinitionMap.put(beanName, beanDefinition);
//将 bean name 添加入 beanDefinitionNames 中
this.beanDefinitionNames.add(beanName);
//将 bean name 从 manualSingletonNames 中删除
this.manualSingletonNames.remove(beanName);
}
//清空数组
this.frozenBeanDefinitionNames = null;
}
//2.4
if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
先来关注这行代码:
((AbstractBeanDefinition) beanDefinition).validate();
追踪一下这行代码:
//AbstractBeanDefinition.class
public void validate() throws BeanDefinitionValidationException {
if (hasMethodOverrides() && getFactoryMethodName() != null) {
throw new BeanDefinitionValidationException(
"Cannot combine static factory method with method overrides: " +
"the static factory method must create the instance");
}
if (hasBeanClass()) {
//此方法内部也主要用到了 hasMethodOverrides() ,这里暂时忽略该方法
prepareMethodOverrides();
}
}
这个方法内部使用了 AbstractBeanDefinition 内定义的 hasMethodOverrides() 和 getFactoryMethodName() 方法去判断 beanDefinition 是否有效。同时满足这两个条件则会抛出异常。
根据官方文档的描述,hasMethodOverrides() 为如果 bean factory 重写了 bean 内的方法,就会返回 true;getFactoryMethodName() 为如果存在工厂方法就会返回该方法的名称。
【没有特别理解这几个方法的应用场景,根据网上资料来看,应该和 bean 的反射创建有一些关系】
再来关注这行代码:
this.frozenBeanDefinitionNames = null;
frozenBeanDefinitionNames 是定义在 DefaultListableBeanFactory 中的一个字符串数组,Spring 在完成 bean 注册之后会将 beanDefinitionNames 转成一个数组,并赋值给 frozenBeanDefinitionNames。
【此为 Spring 的一个内存优化操作】
2.3
看一下上述方法的片段:
if (hasBeanCreationStarted()) {
synchronized (this.beanDefinitionMap) { //线程锁
//执行注册操作
this.beanDefinitionMap.put(beanName, beanDefinition);
//用一个新的 list 去替换原来的
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
//检查单例 bean 名称集合
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
先来追踪一下 hasBeanCreationStarted() 这个方法的内部实现:
//AbstractBeanFactory.class
protected boolean hasBeanCreationStarted() {
return !this.alreadyCreated.isEmpty();
}
alreadyCreated 是一个定义在 AbstractBeanFactory 中的集合,用于存放所有已经被创建(不是注册,是创建)的 bean 的名字。在创建和获取 bean 的时候都会去检查该集合。
在 processors bean 和 iocConfig bean 的注册阶段,该集合为空,此方法返回 false。但是要注意,在 person bean 的注册阶段,此时 iocConfig bean 已经被创建出来了,所以此集合是非空的,此方法返回 true。
//创建新列表
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
//老列表被整个添加到新列表中
updatedDefinitions.addAll(this.beanDefinitionNames);
//添加 beanName 到新列表中
updatedDefinitions.add(beanName);
//替换
this.beanDefinitionNames = updatedDefinitions;
beanDefinitionNames 是一个定义在 DefaultListableBeanFactory 中的列表,用来存放所有注册的 bean 的名字。
if (this.manualSingletonNames.contains(beanName)) {
//新建一个集合,并且将 manualSingletonNames 集合放入新集合中
Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
//删除这个 bean name
updatedSingletons.remove(beanName);
//替换
this.manualSingletonNames = updatedSingletons;
}
manualSingletonNames 是一个定义在 DefaultListableBeanFactory 中的集合,用来存放已经被创建的单例 bean 的名字。因为是单例的,所以不允许重名 bean 的存在,这可能也是 Spring 这里使用集合的原因。
【Spring 的对于内存的优化精确到了每一个列表和集合的容量大小】
进入这个 if 判断条件的情况下,必然是这个 bean 还没有被创建,所以如果这个 bean 已经被放在在这个集合里,就需要删除。正常情况下 bean 的注册过程应该都不会进入执行这个代码片段。
2.4
看一下上述方法的片段:
if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
判断条件中的 existingDefinition 是上方定义的一个 BeanDefinition :
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
一般来说等于 null。
而 containsSingleton(…) 方法具体的实现是在 DefaultSingletonBeanRegistry 中:
//DefaultSingletonBeanRegistry.class
public boolean containsSingleton(String beanName) {
return this.singletonObjects.containsKey(beanName);
}
上面文章中提到过,singletonObjects 是最终保存单例 bean 的 map 对象。
综合来看就是此判断条件可以理解为:如果该 bean 已经注册或者已经被创建,则返回 true,若均未则返回 false。所以一般正常的注册流程是不会执行 resetBeanDefinition(…) 方法的。
关于 resetBeanDefinition(…) 方法,不展开讲了,大致来说就是此方法内部会重新去创建该 bean。
到此为止,reader 已经创建完毕,并且 Spring 使用到的 processors 也已经注册完毕。DefaultListableBeanFactory.registerBeanDefinition 方法非常重要,后面 config bean 和 person bean 的注册也是使用这个方法。
2.5
回到原点:
//AnnotationConfigApplicationContext.class
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this); //2.4
}
本例中暂时没有用到 ClassPathBeanDefinitionScanner,因为没有扫描包路径的方式去获取 bean。所以此处略讲一下 ClassPathBeanDefinitionScanner 的创建。
其构造方法有多层调用,最终的逻辑代码如下:
//ClassPathBeanDefinitionScanner.class
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
Environment environment, @Nullable ResourceLoader resourceLoader) {
//参数非空效验
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
//此处的 registry 是 AnnotationConfigApplicationContext
this.registry = registry;
//Spring 扫描包路径的过滤策略
//useDefaultFilters = true
if (useDefaultFilters) {
registerDefaultFilters();
}
//存入环境对象,此处一个使用无参构造器创建出来的 StandardEnvironment 对象
setEnvironment(environment);
//存入 resourceLoader,此处为 AnnotationConfigApplicationContext
setResourceLoader(resourceLoader);
}
【暂时不展开了】