本文章是我耗时三天多的时间完成的,由于时间的限制,再加上自己能力有限,所以本文章难免会有不足之处,同时Spring的源码还是比较庞大的,要真的讲的细是很不容易的,而对于这篇文章我的定位级别是入门,大家可以当成笑话去看,我会把Spring中的Bean的注册流程大概的说一下,包括循环依赖,虽然不是很细,但是为了保证本文章的质量,有些东西我决定不说,而这些东西没说到不代表我以后不会说,因为后续,我将会更新到第二版,当然,第二版的发布不会在本文章进行覆盖,而是单独发一篇出来,好,废话不多说,让我们开始吧!!!
1. 开胃菜
在走源码之前呢,我们得有心理准备,先上一道开胃菜。
相信我们在学Spring的时候,都听说过Spring容器是一个map,而事实也正是如此,好,到这先打住,因为第一节是开胃菜嘛,所以,我先引入一个东西,叫BeanDefinition,在讲它之前,我们先做如下工作,用案例来说话,如下:
Person类:
package com.cht.domain;
public class Person {
private String name;
private Integer age;
public Person(){
System.out.println("person构造方法被调用");
}
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;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
Test类:
package com.cht.test;
import com.cht.domain.Person;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.*;
public class Test {
public static void main(String[] args) {
BeanDefinition beanDefinition
= new RootBeanDefinition(Person.class);
System.out.println(beanDefinition);
}
}
BeanDefinition是一个接口,RootBeanDefinition是其实现类,它的括号中传入的是Person类对象,也就是它把传入的对象封装成BeanDefinition,看如下输出结果:
Root bean: class [com.cht.domain.Person]; scope=; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null
是不是觉得似曾相识?没错,BeanDefinition这个类就是对bean对象的一种描述,既然这样,我们可以写一个xml,如下:
beans.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="person" class="com.cht.domain.Person" scope="prototype">
<property name="name" value="小陈"/>
<property name="age" value="21"/>
</bean>
</beans>
让我们通过读取xml配置信息,来获取它里面的BeanDefinition信息吧,如下:
Test类:
package com.cht.test;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.*;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
public class Test {
public static void main(String[] args) {
//BeanDefinition注册器
BeanDefinitionRegistry beanDefinitionRegistry =
new SimpleBeanDefinitionRegistry();
//BeanDefinition读取器,需传入注册器,注册到哪?注册到一个map中。
BeanDefinitionReader beanDefinitionReader =
new XmlBeanDefinitionReader(beanDefinitionRegistry);
//BeanDefinition读取器加载配置文件,把配置文件里的每个bean对象封装成BeanDefinitions,由注册器负责注册到map中。
beanDefinitionReader.loadBeanDefinitions("beans.xml");
//通过注册器获取BeanDefinition,说白了,就是从map中根据key的值取,而这个key,就是bean对象的id
BeanDefinition person = beanDefinitionRegistry.getBeanDefinition("person");
//打印出BeanDefinition信息,比如是否单例呀,是否懒加载呀等等
System.out.println(person);
System.out.println("========根据BeanDefinition获取具体信息========");
System.out.println(person.getBeanClassName());
System.out.println(person.getScope());
System.out.println(person.getPropertyValues().get("name"));
System.out.println(person.getPropertyValues().get("age"));
}
}
如下结果:
Generic bean: class [com.cht.domain.Person]; scope=prototype; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [beans.xml]
========根据BeanDefinition获取具体信息========
com.cht.domain.Person
prototype
TypedStringValue: value [小陈], target type [null]
TypedStringValue: value [21], target type [null]
注意,Spring是把xml(或者注解)中的所有bean都封装成BeanDefinition的,如果我们从xml中获取的是不存在的bean,会报如下错误:
public class Test {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
Object a = applicationContext.getBean("a");
System.out.println(a);
}
}
错误信息如下:
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'a' available
在beans.xml文件中是不是只有id为person的bean呀,有没有id为a的bean?是不是压根没有,没有就报错,但最主要的是看它报的是什么错,如上,也就是NoSuchBeanDefinitionException,翻译过来就是没有这个Bean定义,Bean定义就是BeanDefinition。
总之一句话,BeanDefinition就是用来描述bean信息的,注意它区别与Class类,然后在如上上代码出现过几个我们不认识的类,比如BeanDefinitionReader和BeanDefinitionRegistry,一个读取器,一个注册器。读取器就是用来读取信息,封装成BeanDefinition的,上面注释也说了。它有两个比较重要的实现类,分别是XmlBeanDefinitionReader和PropertiesBeanDefinitionReader,从字面意思上可以猜出,一个是针对xml格式,一个是针对properties格式的,毕竟bean的来源不一定来自xml,是不是也有可能是注解,Properties这些呀。它有如下体系图:
注意AnnotatedBeanDefinitionReader不是BeanDefinitionReader的实现类。好,那么BeanDefinitionReader是借助什么来注册BeanDefinition的?是不是就是BeanDefinitionRegistry呀,而我上面只是说了注册到一个map中,那么这个map是什么map?答案是beanDefinitionMap,它是DefaultListableBeanFactory类中的一个属性,如下:
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
.....
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap(256);
.....
}
看到key和value了没有,其中value是不是放的是BeanDefinition类型的呀,刚好这个我们不用愁,因为BeanDefinitionReader帮我们做了,BeanDefinitionRegistry只是负责put而已。后面,如果我们要获取BeanDefinition信息,说白了,就是从这个map中根据key去取罢了,只是BeanDefinitionRegistry帮我们封装了,也就是我们调用的getBeanDefinition方法。下一个是DefaultListableBeanFactory类,它可是一个功能强大的类,为什么这么说,如下体系图:
我说的那个类在最下面,看到没有,在它的上面是不是继承或实现了一堆的BeanFactory,所以,明白了吧,如果明白了,看看它的顶层接口是谁,是不是我们非常熟悉的BeanFactory接口呀,我们以前在学Spring基础的时候,还用它跟ApplicationContext进行比较呢,好像是一个Bean会立即实例化,一个不会立即实例化是不是,这我就不说了,而且从如上体系图我们也可以找到ApplicationContext的存在,可见从功能上来说ApplicationContext的功能要比BeanFactory的功能更加的丰富一点。其它的我就说一下HierarchicalBeanFactory吧,它里面有两个属性,如下:
public interface HierarchicalBeanFactory extends BeanFactory {
@Nullable
BeanFactory getParentBeanFactory();
boolean containsLocalBean(String var1);
}
它是干嘛的呢,我们用案例来说话吧,如下:
AService类:
package com.cht.services;
import org.springframework.stereotype.Service;
@Service
public class AService {
public AService(){
System.out.println("AService被调用");
}
}
BService类:
package com.cht.services;
import org.springframework.stereotype.Service;
@Service
public class BService {
public BService(){
System.out.println("BService被调用");
}
}
Test类:
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext
= new AnnotationConfigApplicationContext(AService.class);
AnnotationConfigApplicationContext applicationContext1
= new AnnotationConfigApplicationContext(BService.class);
applicationContext1.setParent(applicationContext);
Object aService = applicationContext1.getBean("AService");
System.out.println(aService);
}
}
按道理来说,applicationContext1是获取不到AService这个bean定义的,但是,它获取到了,为什么?看代码第7行,它设置了一个父类,这句话是重点,正因为这样,它才获取到了,那好,HierarchicalBeanFactory就发挥它的作用了,比如它可以判断它获取的这个bean定义是不是它本身就具备的bean定义,像AService就不是,因为它是父类的applicationContext,如下:
boolean islocal = ((HierarchicalBeanFactory) applicationContext1).containsLocalBean("AService");
boolean islocal1 = ((HierarchicalBeanFactory) applicationContext1).containsLocalBean("BService");
System.out.println(islocal);
System.out.println(islocal1);
结果如下:
false
true
再说一个,ListableBeanFactory,它跟BeanFactory的区别是,BeanFactory只能获取单个Bean,而ListableBeanFactory可以获取多个Bean,这个大家可以点进去看。
2. 走进源码
先做以下准备:
Spring版本:
版本大家还是要注意一下,因为不同的版本源码都有相应的变化,当然了,就算不一样,也不影响学习。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.3</version>
</dependency>
AppConfig类:
package com.cht.config;
import com.cht.services.BService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.cht")
public class AppConfig {
public AppConfig(){
System.out.println("AppConfig被调用");
}
@Bean
public BService bService(){
return new BService();
}
}
AService类:
package com.cht.services;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;
@Service
public class AService implements ApplicationContextAware{
private ApplicationContext applicationContext;
public AService(){
System.out.println("AService被调用");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
// TODO Auto-generated method stub
this.applicationContext = applicationContext;
}
}
BService类:
package com.cht.services;
public class BService {
public BService(){
System.out.println("BService被调用");
}
}
CService类:
package com.cht.services;
public class CService {
public CService(){
System.out.println("CService被调用");
}
}
DService类:
package com.cht.services;
public class DService {
public DService(){
System.out.println("DService被调用了");
}
}
DServiceBean类:
package com.cht.services;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.stereotype.Service;
@Service
public class DServiceBean implements FactoryBean<DService>{
public DServiceBean(){
System.out.println("DServiceBean被调用");
}
@Override
public DService getObject() throws Exception {
// TODO Auto-generated method stub
return new DService();
}
@Override
public Class<?> getObjectType() {
// TODO Auto-generated method stub
return DService.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
Test类:
package com.cht.test;
import com.cht.config.AppConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext context
= new AnnotationConfigApplicationContext(AppConfig.class);
}
}
按住ctrl,鼠标移到对应的位置,如下:
点进去,如下:
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
register(componentClasses);
refresh();
}
先看第2行,依然是ctrl加鼠标,进入this(),如下:
public AnnotationConfigApplicationContext() {
...
this.reader = new AnnotatedBeanDefinitionReader(this);
...
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
因为Spring版本的原因,以上AnnotationConfigApplicationContext()方法里不单单只有我上面显示的两句代码,还有其它的代码,只不过我不可能一句一句代码的讲,我只会挑重点讲,同时也避免看的麻烦,所以我就把一些我自认为无关紧要的代码省略掉,用三个点来表示,也许后续在第2版中,有些此处遗漏的知识点我会在第二版中说明,所以,此处先跟着我走完整个流程再说,而不是一味挑细节,这样学起来才不会有压力,那好,让我们继续,此处,要明白,我们已经跳到AnnotationConfigApplicationContext类的构造方法里了,但是因为AnnotationConfigApplicationContext类它有父类,所以它要先调用父类的构造方法,如果父类还有父类,那么继续调父类的父类的构造方法,比如AnnotationConfigApplicationContext的父类是GenericApplicationContext,GenericApplicationContext的父类是AbstractApplicationContext,AbstractApplicationContext的父类是DefaultResourceLoader,那么一条链下去就是如下:
public DefaultResourceLoader() {
}
public AbstractApplicationContext() {
this.resourcePatternResolver = getResourcePatternResolver();
}
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
重点关注GenericApplicationContext()方法,可以看出,它实例化了DefaultListableBeanFactory类,这个类上面简单说过,好,到这为止,先记住,它一开始实例化了DefaultListableBeanFactory,接着看AnnotationConfigApplicationContext(this)方法,先看此处的this代表谁,很明显,此处的this代表本类,也就是AnnotationConfigApplicationContext,我们也可以先进入AnnotatedBeanDefinitionReader(this),如下:
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
this(registry, getOrCreateEnvironment(registry));
}
可以看出,此时的this指的是BeanDefinitionRegistry,首先要知道,AnnotationConfigApplicationContext这个类的继承关系,如下:
public class AnnotationConfigApplicationContext
extends GenericApplicationContext
public class GenericApplicationContext
implements BeanDefinitionRegistry
所以,AnnotationConfigApplicationContext这个类是不是可以做为this传入AnnotatedBeanDefinitionReader的方法参数中呀!继续往下说,现在我们进入的是不是AnnotatedBeanDefinitionReader构造方法,参数是BeanDefinitionRegistry,有没有一种似曾相识,我在开胃菜那节是不是有演示过,忘记可以往上翻,继续,选择this,进入,如下:
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
Assert.notNull(environment, "Environment must not be null");
this.registry = registry;
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
Assert.notNull是什么意思呢?它表示传递进来的参数是否不为null,我们可以来测试一下,如下:

了解一下就好,然后下一个,this.registry = registry;就不说了,
而this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);暂且不说,先知道它把ConditionEvaluator给实例化好了,看下一个,AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);,选中registerAnnotationConfigProcessors进去,如下:
public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
registerAnnotationConfigProcessors(registry, null);
}
继续点进去,如下:
registerAnnotationConfigProcessors方法(主方法1):
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) {
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
//相当于Comparator<Object> dependencyComparator = new AnnotationAwareOrderComparator();
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
//相当于AutowireCandidateResolver autowireCandidateResolver = new ContextAnnotationAutowireCandidateResolver();
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
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));
}
// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
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));
}
// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
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;
}
看起来代码有点多,但后面很多都是重复的,比如我们是不是能看到有多个registerPostProcessor呀,register这个单词表示注册,再熟悉不过了,主要是PostProcessor,表示后置处理器或者增强器,都是一个意思,在以上方法中出现六次,其实对应着spring的六个内置处理器,为后续我们在操作我们自定义的bean定义做好准备,这六个内置处理器我不会全部说,大概会说其中的一两个吧,好,反正要明白的是,在这里,Spring会注册六个内置的处理器,注册到哪?也就是我上面说过的beanDefinitionMap,我们先从第4行说起,慢慢分析,看unwrapDefaultListableBeanFactory(registry),点进去,如下:

还知道registry指的是谁吧,是不是就是AnnotationConfigApplicationContext呀,而它的父类是不是GenericApplicationContext,所以,进入else if里,return的就是一个我前面说过的那个重要的类DefaultListableBeanFactory,因为该类早就实例化好了,所以就直接return过来,不需要重新new了,这样,DefaultListableBeanFactory这个实例就拿到了,好,看主方法1的第16行,
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);,说下BeanDefinitionHolder,只要我们打开BeanDefinitionHolder,我们就会发现它里面有三个属性,如下:
public class BeanDefinitionHolder implements BeanMetadataElement {
private final BeanDefinition beanDefinition;
private final String beanName;
//@Nullable表示该属性可以为空
@Nullable
private final String[] aliases;
public BeanDefinitionHolder(BeanDefinition beanDefinition, String beanName) {
this(beanDefinition, beanName, (String[])null);
}
public BeanDefinitionHolder(BeanDefinition beanDefinition, String beanName, @Nullable String[] aliases) {
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
Assert.notNull(beanName, "Bean name must not be null");
this.beanDefinition = beanDefinition;
this.beanName = beanName;
this.aliases = aliases;
}
public BeanDefinitionHolder(BeanDefinitionHolder beanDefinitionHolder) {
Assert.notNull(beanDefinitionHolder, "BeanDefinitionHolder must not be null");
this.beanDefinition = beanDefinitionHolder.getBeanDefinition();
this.beanName = beanDefinitionHolder.getBeanName();
this.aliases = beanDefinitionHolder.getAliases();
}
........
........
}
可以看出,BeanDefinitionHolder封装了BeanDefinition,同时也包括beanName以及aliases,aliases就是别名的意思,因为一个Bean可以有多个别名,所以类型是一个数组,比如如下:
<alias name="person" alias="p1"/>
<alias name="person" alias="p2"/>
<alias name="person" alias="p3"/>
<bean id="person" class="com.cht.entity.Person" >
<property name="name" value="小胖"/>
<property name="age" value="23"/>
</bean>
那么当我们要获取id为person的这个Bean的时候,我们不仅可以根据id来获取,也可以通过别名来获取,也就是p1,p2,p3这些,如下:
到这,不管怎样,我们知道了BeanDefinitionHolder只不过是封装了我们的BeanDefinition,Bean的名字,Bean的别名而已,要明白它的作用,我们继续往下看,到下面这一步,也就是主方法1的第18行到第22行,我就把它抽取出来,如下:
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
先明白CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME代表什么意思,如下:
public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalConfigurationAnnotationProcessor";
知道代表谁了之后,下一步就让我们点进containsBeanDefinition里去,如下:

选中containsBeanDefinition,并Ctrl+Alt+B,在弹出的框中选择第二个,进去,如下:
public boolean containsBeanDefinition(String beanName) {
Assert.notNull(beanName, "Bean name must not be null");
return this.beanDefinitionMap.containsKey(beanName);
}
选中containsKey方法,进入ConcurrentHashMap类,如下:
public boolean containsKey(Object key) {
return get(key) != null;
}
说白了,就是从beanDefinitionMap中,看看有没有一个key叫org.springframework.context.annotation.internalConfigurationAnnotationProcessor的,因为第一次,所以获取不到,不到就是null,而null等于null,所以get(key) != null的结果为false,然后一直return,return到if判断,也就是if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {,进行取反,false取反为true,所以成立,进入。
接着就到这里了,如下:
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
以上就只需要知道它把传入进来的ConfigurationClassPostProcessor类包装成一个BeanDefinition就行了。主要说的就是beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));这个东西,让我们点进registerPostProcessor方法里,如下:
private static BeanDefinitionHolder registerPostProcessor(
BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(beanName, definition);
return new BeanDefinitionHolder(definition, beanName);
}
看如上代码的第4行,registry是不是BeanDefinitionRegistry类型的,它调用了一个方法,叫registerBeanDefinition,直译过来是注册bean定义,而我在开胃菜那节是不是说过BeanDefinitionRegistry是一个注册器,注册器是干嘛的,是不是用来把BeanDefinition注册到一个map中的,什么map?是不是beanDefinitionMap?所以,如果我们选中registerBeanDefinition,进去该方法的话,我们是不是能看到一个put的操作?如下:
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
this.beanFactory.registerBeanDefinition(beanName, beanDefinition);
}
继续点击:
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
...
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
...
else {
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
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;
...
}
}
else {
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
...
}
...
}
...
}
第一次,beanDefinitionMap里肯定是没有你要的key的,所以existingDefinition恒等于null,所以它进入else里,在else里不管是走哪个分支,最终都会put到beanDefinitionMap中,当然beanDefinitionNames也有相应变化。只要记住这点就行了,好,那么到这为止,beanName是谁,我就直接说了,beanName就是那个长长的CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME,当然它不是,它是一个常量来着,而是它对应的值,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,beanDefinition就是ConfigurationClassPostProcessor.class封装的beanDefinition,到这registry.registerBeanDefinition(beanName, definition);也就执行完了,到下一个就是return一个BeanDefinitionHolder出去,就不说了,很简单,反正最终都会加入到Set beanDefs = new LinkedHashSet<>(8);里面去,因为它执行了beanDefs.add(BeanDefinitionHolder holder)操作。好,既然Spring把它内置的六个内置处理器加入到beanDefinitionMap中了,那我们是不是可以查看一下,如下:
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
String[] beanDefinitionNames = context.getBeanDefinitionNames();
for(String beanDefinitionName:beanDefinitionNames){
Object bean = context.getBean(beanDefinitionName);
System.out.println(beanDefinitionName+"===>"+bean);
}
结果如下:
org.springframework.context.annotation.internalConfigurationAnnotationProcessor===>org.springframework.context.annotation.ConfigurationClassPostProcessor@1a561cf
org.springframework.context.annotation.internalAutowiredAnnotationProcessor===>org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor@1938003
org.springframework.context.annotation.internalCommonAnnotationProcessor===>org.springframework.context.annotation.CommonAnnotationBeanPostProcessor@13b5d16
org.springframework.context.event.internalEventListenerProcessor===>org.springframework.context.event.EventListenerMethodProcessor@b1cc93
org.springframework.context.event.internalEventListenerFactory===>org.springframework.context.event.DefaultEventListenerFactory@646153
...
以上结果是Spring内置的后置处理器有5个,但不管是几个,都不影响,好,现在上面所列出来的是所有的beanDefinitionNames,我们先看第一个,也就是ConfigurationClassPostProcessor,它的继承体系如下:
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor
关注点在BeanFactoryPostProcessor,它是一个接口,如下:
@FunctionalInterface
public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
它的用处就是可以用来对我们的beanDefinition做二次修改的,比如我们可以写一个类来实现BeanFactoryPostProcessor接口,重写它的方法,如下:
package com.cht.processor;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;
@Component
public class TxBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition aService = beanFactory.getBeanDefinition("AService");
//充分显示对BeanDefinition的二次修改
aService.setScope("prototype");
}
}
那么以上postProcessBeanFactory方法何时被执行,注意,该类要想发挥作用,记得加上@Component注解啥的让它交给Spring去管理,Spring拿到后,会自动帮我们调用的,那什么时候被调用,就是当你准备要拿着beanDefinition去实例化的时候,我们知道,在getBean某某某的时候,我们拿到的是一个实例对象,而不是一个beanDefinition,所以我们就得把我们获取到的beanDefinition信息去实例化成一个真正的对象,而在去实例化的这条路上,可能半路会跳出一个处理器来对你进行拦截,目的有可能是要来修改你的beanDefinition信息的,所以,请注意,我们在beans.xml里写的每个bean标签所对应的属性,在交给Spring去实例化之前都有可能被拦截,被修改,比如单例的bean被修改成多例的bean,如上代码就是一个例子。好,那么既然ConfigurationClassPostProcessor实现了BeanFactoryPostProcessor,那么ConfigurationClassPostProcessor也应该会有修改beanDefinition的功能。最后注意,ConfigurationClassPostProcessor存在的主要意义是用来解析加了@Configuration,@Service,@ComponentScan、@ComponentScans,@Import等注解扫描的类。先知道这点就行了。当然了,在BeanFactoryPostProcessor之前,可以还有一层拦截,它就是BeanDefinitionRegistryPostProcessor,如下:
package com.cht.processor;
import com.cht.domain.Person;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.stereotype.Component;
@Component
public class TxBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
//重点关注
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
int beanDefinitionCount = registry.getBeanDefinitionCount();
System.out.println("bean定义的数量是:"+beanDefinitionCount);
//为Person类构建一个bean定义信息
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Person.class).getBeanDefinition();
registry.registerBeanDefinition("person1",beanDefinition);
int beanDefinitionCount1 = registry.getBeanDefinitionCount();
System.out.println("bean定义的数量是:"+beanDefinitionCount1);
}
//注意下面这个方法是因为BeanDefinitionRegistryPostProcessor继承了BeanFactoryPostProcessor而来的
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
}
结果如下:
bean定义的数量是:11
bean定义的数量是:12
对于BeanFactoryPostProcessor的实现类有ConfigurationClassPostProcessor,还有PlaceholderConfigurerSupport,它可以来对属性的值进行修改,比如我们在xml里是不是曾经写过如下代码:
<bean id="driverManagerDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="username" value="${jdbc.user}"/>
<property name="password" value="${jdbc.password}"/>
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
</bean>
我们知道,如上代码是会被封装成BeanDefinition的,所以PlaceholderConfigurerSupport作为后置处理器是可以拿到BeanDefinition信息的,自然就可以替换属性中的值,此时它拿到的值就是${xxx}格式的占位符,所以我们是不是要对其进行替换成真正的值呀,这样才可以拿去后续的实例化。
那么this.reader = new AnnotatedBeanDefinitionReader(this);就大概的分析完了,总结一下它干了什么事,就是把Spring的几个内置的处理器注册到Spring容器。
下一句,就是分析this.scanner = new ClassPathBeanDefinitionScanner(this);了,Scanner表示扫描器,而这个扫描器对象仅仅是为了我们程序员可以手动调用AnnotationConfigApplicationContext对象的scan方法,而不是Spring默认的Scanner对象,好,此处对于实例化好了的ClassPathBeanDefinitionScanner对象,主要说的是scan方法,比如如下,以前我们是这样的:
AnnotationConfigApplicationContext context
= new AnnotationConfigApplicationContext(AppConfig.class);
还有另一种情况,跟上述代码效果一样,如下:
AnnotationConfigApplicationContext context
= new AnnotationConfigApplicationContext();
context.scan("com.cht");
context.refresh();
我们选中scan方法,进入,如下:
public void scan(String... basePackages) {
...
this.scanner.scan(basePackages);
...
}
如上的this.scanner就是指ClassPathBeanDefinitionScanner,已经早早的就实例化了,而它里有个总要的方法scan,继续点下去,如下:
public int scan(String... basePackages) {
int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
doScan(basePackages);
// Register annotation config processors, if necessary.
...
return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
}
第一个beanCountAtScanStart不用多说,表示BeanDefinition的个数,点doScan(basePackages);方法下去,如下:
doScan方法(主方法2):
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
...
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
for (String basePackage : basePackages) {
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
...
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
首先要看该方法的参数,有三个点,意味着它是可变参数,也就是说,参数个数不固定,比如如下:
context.scan("xxxx","xxxxx");
也就是说,我们可以扫描多个包,那好,既然这样,下面我就要遍历这些包了,注意,它传进来的basePackages变量是数组类型的,所以,看第4行的for (String basePackage : basePackages){,它就会依次遍历我们传进来的参数,只不过我们此时只传了一个参数,是com.cht,好,拿到这个字符串后,传入this.findCandidateComponents(basePackage);方法里,让我们进入,如下:
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
...
... this.scanCandidateComponents(basePackage);
}
继续点击,如下:
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
LinkedHashSet candidates = new LinkedHashSet();
try {
String packageSearchPath = "classpath*:" + this.resolveBasePackage(basePackage) + '/' + this.resourcePattern;
Resource[] resources = this.getResourcePatternResolver().getResources(packageSearchPath);
boolean traceEnabled = this.logger.isTraceEnabled();
boolean debugEnabled = this.logger.isDebugEnabled();
Resource[] var7 = resources;
int var8 = resources.length;
for(int var9 = 0; var9 < var8; ++var9) {
Resource resource = var7[var9];
if (traceEnabled) {
this.logger.trace("Scanning " + resource);
}
if (resource.isReadable()) {
try {
MetadataReader metadataReader = this.getMetadataReaderFactory().getMetadataReader(resource);
if (this.isCandidateComponent(metadataReader)) {
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setResource(resource);
sbd.setSource(resource);
if (this.isCandidateComponent((AnnotatedBeanDefinition)sbd)) {
if (debugEnabled) {
this.logger.debug("Identified candidate component class: " + resource);
}
candidates.add(sbd);
} else if (debugEnabled) {
this.logger.debug("Ignored because not a concrete top-level class: " + resource);
}
} else if (traceEnabled) {
this.logger.trace("Ignored because not matching any filter: " + resource);
}
} catch (Throwable var13) {
throw new BeanDefinitionStoreException("Failed to read candidate component class: " + resource, var13);
}
} else if (traceEnabled) {
this.logger.trace("Ignored because not readable: " + resource);
}
}
return candidates;
} catch (IOException var14) {
throw new BeanDefinitionStoreException("I/O failure during classpath scanning", var14);
}
}
以上方法就很重要了,其中有一个单词有必要说下,它就是candidates,翻译过来叫候选人,在此处的意思是,一个包下是不是有很多类,但是这么多的类我并不一定全部都要,我只要那些加了@Component注解的类啥的,这很好懂吧。我们看第5行, String packageSearchPath = "classpath*:" + this.resolveBasePackage(basePackage) + '/' + this.resourcePattern;,看的出,是字符串拼接,表示classpath*:com/cht/**/*.class,好,下一句,也就是第6行就是获取一个resources资源对象,该resources资源对象是一个数组,这个数组包含了我们指定包下的所有类,那么,获取到所有类,接下来就要遍历这些类了,可以看如上代码或自己debug一下看看我说的是不是对的,然后看第18行,就是看你这个资源对象是否可读,一般是可读的,所以进入,看this.isCandidateComponent(metadataReader),这个就表示你这个资源对象是否进入候选,也就是我前面说的,要对包下所有类进行一一检查,看看你这个类有没有交由我Spring管理,不多说,我也不想点进去,知道意思就行,然后因为此时的资源类对应的类是AppConfig类,所以,成立,进入,接着封装成BeanDefinition信息,最终进入候选名单,看第30行,然后return出去。
让我们回到doScan方法,定位到第5行,此时此刻,findCandidateComponents已经执行完了,candidates也有值了,也就是说,Spring已经把一些不相关的类过滤掉了,那好,接下来看第6行,注意是doScan方法的第6行,就是要来遍历那些候补的类了,下一步,看主方法2的第9行,选中generateBeanName进入,如下:
AnnotationBeanNameGenerator类:
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
if (definition instanceof AnnotatedBeanDefinition) {
String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition);
if (StringUtils.hasText(beanName)) {
// Explicit bean name found.
return beanName;
}
}
// Fallback: generate a unique default bean name.
return buildDefaultBeanName(definition, registry);
}
看第3行,进入,如下:
protected String determineBeanNameFromAnnotation(AnnotatedBeanDefinition annotatedDef) {
AnnotationMetadata amd = annotatedDef.getMetadata();
Set<String> types = amd.getAnnotationTypes();
String beanName = null;
for (String type : types) {
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(amd, type);
if (attributes != null) {
...
if (isStereotypeWithNameValue(type, metaTypes, attributes)) {
Object value = attributes.get("value");
if (value instanceof String) {
String strVal = (String) value;
if (StringUtils.hasLength(strVal)) {
if (beanName != null && !strVal.equals(beanName)) {
throw new IllegalStateException("Stereotype annotations suggest inconsistent " +
"component names: '" + beanName + "' versus '" + strVal + "'");
}
beanName = strVal;
}
}
}
}
}
return beanName;
}
看第二行,AnnotationMetadata表示注解元信息,它可以获取候选bean定义的注解信息,到第三行就把所有注解信息拿到了,接着到第五行遍历所有注解,如下:
下一句,就是获取注解的属性了,如下:
很明显,是有属性的,所以它不等于null成立,进入,看第九行,选中isStereotypeWithNameValue方法,点进去,如下:
protected boolean isStereotypeWithNameValue(String annotationType,
Set<String> metaAnnotationTypes, @Nullable Map<String, Object> attributes) {
boolean isStereotype = annotationType.equals(COMPONENT_ANNOTATION_CLASSNAME) ||
metaAnnotationTypes.contains(COMPONENT_ANNOTATION_CLASSNAME) ||
annotationType.equals("javax.annotation.ManagedBean") ||
annotationType.equals("javax.inject.Named");
return (isStereotype && attributes != null && attributes.containsKey("value"));
}
参数annotationType指的就是传入进来的type,而这个type是不是就是org.springframework.context.annotation.Configuration。然后第二个参数,如下:
第三个参数就不用说了,让我们看如上代码的第四行,看看isStereotype是true还是false,那么annotationType.equals(COMPONENT_ANNOTATION_CLASSNAME)中的COMPONENT_ANNOTATION_CLASSNAME表示什么呢?如下:
private static final String COMPONENT_ANNOTATION_CLASSNAME = "org.springframework.stereotype.Component";
不用讲,为false,再看metaAnnotationTypes.contains(COMPONENT_ANNOTATION_CLASSNAME),这个就为true了,因为是||的关系,所以以上代码的四个条件中只要有一个true,那么结果就为true,好,看第九行,前两个条件不用说,主要说attributes.containsKey(“value”),也就是有没有一个属性名叫value的,当然有,那么最终return出去的就是true,让我们回到determineBeanNameFromAnnotation方法,看第10行,获取到的value值是"",到第11行,判断""是不是一个字符串,为true,进入,但是到第13行的时候就为false了,所以最终执行到第24行,return一个beanName出去,此时的beanName为null。如果我们把Configuration注解换成ComponentScan,那么到isStereotypeWithNameValue这关就已经过不去了,毕竟我们是要对bean起一个beanName,肯定不是根据ComponentScan来取的,所以最终return一个null出去,这点跟前面的Configuration注解return一个null出去也是有想通之处的,其实我要说明的就是,在AppConfig这个类上其实是可以不加@Configuration这个注解的,一样是可以根据getBean(“appConfig”)来获取AppConfig对象的,不信可以试一下,我已经试过了,那么要想不让它返回null,那肯定要满足StringUtils.hasLength(strVal)为true,也就是我们获取的@Configuration注解里的value属性必须有值,像如下这样:
@Configuration("APPConfig")
这样子StringUtils.hasLength(strVal)就为true了,好,回到generateBeanName方法,看第三行,如果beanName为null,说明@Configuration注解的value为空,那么它的名字就由Spring来默认指定,如果不为null,就说明我们已经给它取名字了,叫APPConfig,所以,第四行就开始判断,判断我们是否有为它取名字,也就是StringUtils.hasText(beanName),我们可以看一下,如下:
System.out.println(StringUtils.hasText(null));
System.out.println(StringUtils.hasText("hahaha"));
结果如下:
false
true
既然这样,如果我们有给它指定名字,那么就会到第6行,直接return出去,否则就让Spring默认帮我们起名,定位到第10行,进入buildDefaultBeanName方法,如下:
protected String buildDefaultBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
return buildDefaultBeanName(definition);
}
继续进入,如下:
protected String buildDefaultBeanName(BeanDefinition definition) {
String beanClassName = definition.getBeanClassName();
...
String shortClassName = ClassUtils.getShortName(beanClassName);
return Introspector.decapitalize(shortClassName);
}
beanClassName和shortClassName如下:

好,选中decapitalize进去,如下:
public static String decapitalize(String name) {
if (name == null || name.length() == 0) {
return name;
}
if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) &&
Character.isUpperCase(name.charAt(0))){
return name;
}
char chars[] = name.toCharArray();
chars[0] = Character.toLowerCase(chars[0]);
return new String(chars);
}
注意,以上方法解决了我之前的困惑,比如以AService为例,当我们去getBean(“aService”)的时候发现获取不到,怎么会获取不到呢?不是默认以类名首字母小写吗?没道理呀,经过尝试修改,发现getBean(“AService”)就可以获取到,这是为什么?答案就在如上方法里,主要看如上方法的第五行,看Character.isUpperCase(name.charAt(1)) &&Character.isUpperCase(name.charAt(0))就明白了,charAt(1)里的1代表索引为1的字符,以AppConfig为例,索引为1的字符就为p,它是大写吗?是不是不是,不是Character.isUpperCase(name.charAt(1))就为false,所以整个条件就不成立,就不会进入里面去直接return一个name,而这个name是不是就是类名呀!好,既然不是,那么就到第九行了,这里相信大家都看的懂,我就不解释了,很简单,是不是最终就return一个类名的首字母小写出去呀。
让我们回到主方法2那里去,也就是doScan方法里,看向第11行,也就是checkCandidate(beanName, candidate),它里面会检查你传入进来的beanName在beanDefinitionMap里面有没有,如果没有,那么checkCandidate就为true,下面就会帮你注册,第12行封装成BeanDefinitionHolder没问题吧,然后第13行跟代理有关,不管它,主要看第15行和第16行,让我们把目光看向第16行,进入,如下:
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// Register bean definition under primary name.
String beanName = definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// Register aliases for bean name, if any.
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
很简单,不多说。那么到处为止,scan方法就基本上说完了,现在就让我们回到 AnnotationConfigApplicationContext(Class<?>… componentClasses)方法里吧,this()部分已经结束了,看register(componentClasses);,让我们跟进去,如下:
public void register(Class<?>... componentClasses) {
...
this.reader.register(componentClasses);
...
}
继续:
public void register(Class<?>... componentClasses) {
for (Class<?> componentClass : componentClasses) {
registerBean(componentClass);
}
}
注意,参数是可变参数,也就是new AnnotationConfigApplicationContext(“xxx”,“xxx”);所以上述代码才会去循环遍历,我这里就只有一个,也就是AppConfig,好,进入registerBean,如下:
public void registerBean(Class<?> beanClass) {
doRegisterBean(beanClass, null, null, null, null);
}
再继续:
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
@Nullable BeanDefinitionCustomizer[] customizers) {
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
abd.setInstanceSupplier(supplier);
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
...
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
看第五行,不用说,是把AppConfig封装成一个BeanDefinition,主要看第六行,让我们进入shouldSkip方法,如下:
public boolean shouldSkip(AnnotatedTypeMetadata metadata) {
return shouldSkip(metadata, null);
}
继续:
public boolean shouldSkip(@Nullable AnnotatedTypeMetadata metadata, @Nullable ConfigurationPhase phase) {
if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) {
return false;
}
if (phase == null) {
if (metadata instanceof AnnotationMetadata &&
ConfigurationClassUtils.isConfigurationCandidate((AnnotationMetadata) metadata)) {
return shouldSkip(metadata, ConfigurationPhase.PARSE_CONFIGURATION);
}
return shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN);
}
List<Condition> conditions = new ArrayList<>();
for (String[] conditionClasses : getConditionClasses(metadata)) {
for (String conditionClass : conditionClasses) {
Condition condition = getCondition(conditionClass, this.context.getClassLoader());
conditions.add(condition);
}
}
AnnotationAwareOrderComparator.sort(conditions);
for (Condition condition : conditions) {
ConfigurationPhase requiredPhase = null;
if (condition instanceof ConfigurationCondition) {
requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
}
if ((requiredPhase == null || requiredPhase == phase) && !condition.matches(this.context, metadata)) {
return true;
}
}
return false;
}
先看第2行的metadata.isAnnotated(Conditional.class.getName()),注意,有种注解叫@Conditional(xxx)注解,该注解标注在某一个类上,就相当于该类的一个拦截器,它决定了被标注的这个类是否能被实例化,这个@Conditional注解大家私下自己去了解,那么metadata.isAnnotated(Conditional.class.getName())就代表AppConfig类是否有@Conditional(xxx)标注,此时是没有的,没有就是false,取反就是true,又因为是||,所以成立,进入,return一个false出去,到doRegisterBean方法,所以this.conditionEvaluator.shouldSkip(abd.getMetadata())条件不成立,就会进入后续的注册中,我们来演示一下@Conditional效果,先做如下准备:
public class CustomConditionalImpl implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return false;
}
}
然后呢在AppConfig类上加上@Conditional(value = CustomConditionalImpl.class)注解,注意@Conditional注解上的value属性值是CustomConditionalImpl.class,好,再来测试,就跟上述没有@Conditional注解的类完全不一样了,也就是metadata.isAnnotated(Conditional.class.getName())为true,然后true取反就是false,所以整体为false,为false就不会进入,不会进入就不会直接return一个false。好,既然不会直接return false,那么这次就会来到第6行,此时phase为null,没问题,进入,看向第八行,找到isConfigurationCandidate方法,这个方法我就不点进去了,该方法的作用是判断你目前的类是否是一个配置类,它会根据你当前类上是否有这几种注解来判断@Component,@ComponentScan,@Import,@ImportResource,当然也包括@bean,如果有我刚才说的这几种注解的其中一种,那么将会返回true,否则返回false,很明显,当前的AppConfig类上是有@ComponentScan注解的,同时也有@bean注解,所以返回true,也就是ConfigurationClassUtils.isConfigurationCandidate((AnnotationMetadata) metadata))就为true,所以进入shouldSkip(metadata, ConfigurationPhase.PARSE_CONFIGURATION);里,那好,什么时候会进入else里呢?就是当我上面说的五个注解全部没有的时候,注意不能多出一个@bean注解,其实你看它的第二个参数也能明白,也就是ConfigurationPhase.REGISTER_BEAN,看看那一串大写,是不是叫注册Bean呀。接下来,不管走的是ConfigurationPhase.PARSE_CONFIGURATION还是ConfigurationPhase.REGISTER_BEAN也好,它会再次调用shouldSkip方法,如下:
所以,此时此刻,它再重新执行该方法的时候,phase不再为null了,所以就会跳过它,继续往下走,以ConfigurationPhase.PARSE_CONFIGURATION为例,走到如下部分:
下一句,也就是第17行,拿到condition,可以理解成底层用了反射。下一步再是加入到List conditions = new ArrayList<>();中,然后看下一句,第22行,也就是AnnotationAwareOrderComparator.sort(conditions);,这个是用来排序的,可以看这篇文章,当然,不是我的,地址:https://www.bbsmax.com/A/gGdXolr754/,可以拖到最后,也就是如下界面:
看第24行,开始遍历Condition对象,在遍历的过程中会遇到ConfigurationPhase,所以,我们对CustomConditionalImpl加点东西,如下:
所以,如下:
往下看,第29行,我把它取出来,如下:
if ((requiredPhase == null || requiredPhase == phase) && !condition.matches(this.context, metadata)) {
return true;
}
看前半部分,也就是(requiredPhase == null || requiredPhase == phase),requiredPhase恒等于null,没问题,因为它return的就是null,所以整体为true,那看requiredPhase == phase,这肯定就为false咯,要想让它成立,我们也可以这样,注意,phase我们上面是不是见过,在此处这里指的是ConfigurationPhase.PARSE_CONFIGURATION,所以我们让它返回ConfigurationPhase.PARSE_CONFIGURATION也是一样的,如下:
public ConfigurationPhase getConfigurationPhase() {
return ConfigurationPhase.PARSE_CONFIGURATION;
}
效果跟返回null是一样的,好,我们再看最后一个条件!condition.matches(this.context, metadata),先忽略取反,看condition.matches(this.context, metadata),首先,matches是不是一个方法,如下:
返回的是不是false,所以取反是不是true,好,看如下代码,看看最终是true还是false,如下:
public class CustomConditionalImpl implements Condition,ConfigurationCondition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
return false;
}
@Override
public ConfigurationPhase getConfigurationPhase() {
// 看源代码可知,返回null是默认的
return null;
}
}
是不是true呀,也就是(requiredPhase == null || requiredPhase == phase) && !condition.matches(this.context, metadata)最终就是true对不对,对的话,进入,return一个true出去,一直return到doRegisterBean方法的如下判断:
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
所以this.conditionEvaluator.shouldSkip(abd.getMetadata())结果就为true,进入,该方法结束,不会进行后续的注册操作,也就是说AppConfig不会被Spring注册到BeanDefinitionMap中,因为AppConfig类上加了@Conditional(value = CustomConditionalImpl.class)注解。其中关注点在matches方法上,如果matches返回的是true,true意味着放行,这样一来,就不会阻碍AppConfig类的注册了。
让我们回到doRegisterBean方法,后面基本说一下,是不是会先获取它的beanName呀,然后在注册到beanDefinitionMap中是不是呀,所以,让我们回到如下方法:
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
register(componentClasses);
refresh();
}
其中的register(componentClasses);是不是就说完了呀,它干嘛了,说白了就是帮我们注册了传进来的componentClasses。
好,看最后一个方法,refresh()方法,进入,如下:
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// 准备工作,调用容器准备刷新的方法,获取容器的当前时间,同时给容器设置同步标识
prepareRefresh();
// 拿到DefaultListableBeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 为beanFactory设置一些属性值
prepareBeanFactory(beanFactory);
try {
// 空方法,不管,可以留给子类扩展使用
postProcessBeanFactory(beanFactory);
...
// 实例化和调用所有已经注册的BeanFactory的后置处理器,并把指定包下符合Spring的主件类注册到Spring中
invokeBeanFactoryPostProcessors(beanFactory);
// 实例化并且注册所有的BeanPostProcessors,在创建bean的前后等执行
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
// 初始化MessageSource组件(做国际化功能;消息绑定,消息解析);
initMessageSource();
// 初始化事件派发器
initApplicationEventMulticaster();
// 子类重写这个方法,在容器刷新的时候可以自定义逻辑;如创建Tomcat,Jetty等WEB服务器
onRefresh();
// 注册应用的监听器。就是注册实现了ApplicationListener接口的监听器bean,这些监听器是注册到ApplicationEventMulticaster中的
registerListeners();
// 实例化所有剩余的(非lazy init)单例。
finishBeanFactoryInitialization(beanFactory);
// 完成context的刷新。主要是调用LifecycleProcessor的onRefresh()方法,并且发布事件(ContextRefreshedEvent)
finishRefresh();
}
....
....
}
}
看第9行,可以看出,obtainFreshBeanFactory()返回的是一个ConfigurableListableBeanFactory对象,我们可以点进去看一下,如下:
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
...
return getBeanFactory();
}
继续:
GenericApplicationContext类:
@Override
public final ConfigurableListableBeanFactory getBeanFactory() {
return this.beanFactory;
}
看beanFactory所对应的类型,如下:
private final DefaultListableBeanFactory beanFactory;
也就是说,DefaultListableBeanFactory实现了ConfigurableListableBeanFactory,而DefaultListableBeanFactory是不是在this()的阶段就已经实例化好了呀,所以就可以直接返回出去咯,而且我们可以看到下面的一些操作都跟beanFactory有关,比如下面的prepareBeanFactory(beanFactory);,好,下一个,我只说重要的方法,其它的可以看我上述的注释,先看第20行,也就是invokeBeanFactoryPostProcessors(beanFactory);,看方法名,很简单,就是调用所有的BeanFactoryPostProcessors后置处理器,那么BeanFactory后置处理器能不能帮我们注册Bean定义呀,是不是可以,注意,在AnnotationConfigApplicationContext构造方法里的第二行是不是已经把AppConfig注册到beanDefinitionMap中了呀,还剩下其它的类没注册到beanDefinitionMap中,那么剩下的就是在invokeBeanFactoryPostProcessors(beanFactory);中完成了,我们可以进去看看,如下:
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
...
}
继续点进去:
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
...
...
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
...
...
}
看方法名,去掉invoke,就是BeanDefinitionRegistryPostProcessors,直译就是Bean定义注册后置处理器,也就是说,该注册器可以完成BeanDefinition的注册,它是一个接口,实现类是ConfigurationClassPostProcessor,定位到它的processConfigBeanDefinitions方法就是了,你一定会看到如下代码:
this.reader.loadBeanDefinitions(configClasses);
loadBeanDefinitions译为加载BeanDefinitions,调用它,自动就会把符号Spring的类put到beanDefinitionMap中了。
再下一个,看第39行,也就是finishBeanFactoryInitialization(beanFactory);,这个方法就很重要了,点进如下:
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
....
....
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
}
继续进入,如下:
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(
(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
.tag("beanName", beanName);
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
smartInitialize.end();
}
}
}
第8行,获取所有的beanName,到第11行,开始遍历所有的beanName,首先,先根据beanName获取到它对应的BeanDefinition信息,此处,因为是第一次循环,所以beanName指的是org.springframework.context.annotation.internalConfigurationAnnotationProcessor,好,接着看第13行,这行判断可是很重要哦,它决定了你的这个Bean是否会被实例化,我们知道,在容器初始化的时候只会去初始化好那些单例bean,并不会把我们在xml里配的所有bean都实例化,那么,我们就好好的看这行判断,先看第一个条件,!bd.isAbstract(),也就是说,你当前的这个bean是不是一个抽象bean,很明显不是,不是就是false,取反为true,再看第二个条件,是否为单例,答案是是,所以也为true,最后一个条件,是否是懒加载,答案为不是,取反所以还为true,那么整体就为true,条件成立,进入,也就是说,如果该bean是抽象bean,或者是非单例的,又或者是懒加载的,在容器初始化阶段都不会被立即实例化,好,明白了之后,进入,又有一个判断,它就是if (isFactoryBean(beanName)) {,也就是判断它是否是FactoryBean,什么意思,还记不记得DServiceBean类,这个类是不是实现了FactoryBean接口,也就是说,只有该类成立,其它因为没实现FactoryBean接口,所以isFactoryBean不成立,不成立就直接进入else里,进行getBean操作,我们先进入getBean方法里,如下:
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
继续:
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
String beanName = transformedBeanName(name);
Object beanInstance;
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 检查此工厂中是否存在 bean 定义
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 没找到 -> 检查父类
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
.tag("beanName", name);
try {
if (requiredType != null) {
beanCreation.tag("beanType", requiredType::toString);
}
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 先初始化Bean所依赖的其它Bean
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
String scopeName = mbd.getScope();
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean 麓" + beanName + "'");
}
Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new ScopeNotActiveException(beanName, scopeName, ex);
}
}
}
catch (BeansException ex) {
beanCreation.tag("exception", ex.getClass().toString());
beanCreation.tag("message", String.valueOf(ex.getMessage()));
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
finally {
beanCreation.end();
}
}
return adaptBeanInstance(name, beanInstance, requiredType);
}
看第5行,也就是String beanName = transformedBeanName(name);,好,transformedBeanName是干嘛的呢?我简单说一下,它有两点,先说其中一点,我们这次以xml为例,在xml里有如下代码,而这如下代码我们在前面已经见过了,但是此处我还是再贴一次,免得往上翻,如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<alias name="person" alias="p1"/>
<bean id="person" class="com.cht.entity.Person" >
<property name="name" value="小胖"/>
<property name="age" value="23"/>
</bean>
</beans>
然后我们在测试类下进行getBean获取,如下:
public class Test {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//注意这里是根据别名获取的
Person person = (Person) context.getBean("p1");
System.out.println(person);
}
}
看以上代码的第5行,是不是有一个方法叫getBean呀,说明什么?你懂的,所以,让我们跟进去,反正无论如何它肯定会经过transformedBeanName(name),那么此时的name是不是就是别名p1呀,好,如下:

而以上的person是不是就是id为person的bean呀,也可以这么理解,表名上是通过别名来getBean(‘p1’)的,但底层是通过getBean(‘person’)来的,这也是为什么我们可以通过别名来获取bean实例的原因。好,这是第一点,不是还有一点吗,另一点就跟FactoryBean有关了,具体点是跟getBean(’&beanName’)有关,你可以还不明白我的意思,关键点在&这里,说到这,就不得不提到FactoryBean了,算了,我简单的说一下,看个效果就行,先准备如下类,也就是前面见到过的DServiceBean类:
package com.cht.services;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.stereotype.Service;
@Service
public class DServiceBean implements FactoryBean<DService>{
public DServiceBean(){
System.out.println("DServiceBean被调用");
}
@Override
public DService getObject() {
// TODO Auto-generated method stub
return new DService();
}
@Override
public Class<?> getObjectType() {
// TODO Auto-generated method stub
return DService.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
不懂FactoryBean可以先去参考别的资料,这里不做解释,具体的放到后面另一篇文章,好,看如下测试类:
AnnotationConfigApplicationContext context
= new AnnotationConfigApplicationContext(AppConfig.class);
System.out.println(context.getBean("DServiceBean").getClass());
看懂了吗,最终的类型是什么?如下:
class com.cht.services.DService
为什么是DService,而不是DServiceBean呢?因为它默认是按照getObject方法而来的,请看DServiceBean的getObject()方法,如果我想获取的是DServiceBean呢?那我们可以试着加上&,如下:
AnnotationConfigApplicationContext context
= new AnnotationConfigApplicationContext(AppConfig.class);
System.out.println(context.getBean("&DServiceBean").getClass());
结果如下:
class com.cht.services.DServiceBean
一样,让我们跟随getBean进去,不用说,肯定会经过transformedBeanName(name),如下:

是不是就把&给除掉了!到这,transformedBeanName(beanName)也就说完了,继续往下看吧,第9行,Object sharedInstance = getSingleton(beanName);,这,就跟三级缓存有关了,一说到缓存,其实说白了就是Map,三级,就是三个Map,它是DefaultSingletonBeanRegistry类里的三个属性,如下:
//一级缓存
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
//三级缓存
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
//二级缓存
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
而getSingleton说白了就是从这三个Map中找,找对应的单例bean,那么为什么要有这三个Map呢?其实准备着三个Map是为了解决循环依赖来的,说到这,可能还不知道循环依赖是什么,很简单,就是A依赖B,B又依赖A,这就是循环依赖,够好懂吧,比如如下:
package com.cht.services;
public class A {
private B b;
}
package com.cht.services;
public class B {
private A a;
}
好,那么我们先来聊聊循环依赖问题,像以上情况,如果按照原始的我们很好解决,比如:
A a = new A();
B b = new B();
a.b = b;
b.a = a;
但是如果是用Spring的话,就有可能造成死循环问题,而三级缓存就恰恰是用来解决死循环问题的,那么死循环是怎么回事呢?因为你new了一个a,new了一个a之后就要对a进行属性赋值了,而a类下的属性是b,也就是b还没赋值,那好,开始赋值,首先,先去单例池里找,有没有B类,有就返回,没有就创建,假设没有,就得new一个B出来,new完后一样要对B类的属性,也就是a赋值,但是a因为还没赋好属性值,此时还是一个空实例,不是一个完整对象,所谓的完整对象就是该对象走完了实例化,属性填充,初始化的过程。所以还不是一个完整的对象,不是一个完整的对象就不能为b类的属性a赋值,好,既然这样,那是不是要走完A类的剩下的过程呀,而A类是不是还没完成属性填充呀,恰恰就是属性填充出了问题,因为A类下的属性是填充一个b,所以,明白了吧,又回到b类这里了,所以,整体就这么循环来,循环去,都是要得到对方一个完整的对象才能结束循环,也就是说,我a类下的属性b,要对其完成赋值操作,必须走完b的整个生命周期,b类下的属性a也一样。
那么该问题怎么解决,因为我说了,它为什么不能完成赋值操作,恰恰因为它赋值的是一个对象,而我要赋值的这个对象必须走完它的实例化,属性填充,初始化这三个过程才可以,所以,我就开始走以上三个过程了,实例化没问题,但是到属性填充就出现问题了,因为它要填充的对象是原来一开始要赋值的那个对象,就是又返回去了,因为都要求对方必须走完三个阶段才能完成赋值,所以出现死循环,而为了解决这个问题,我们针对出现在属性填充的这个问题上,我们可以准备一个Map,也就是一个半成品Map,是三级缓存中的二级缓存,来放空实例对象,也就是经历了实例化阶段,但还没为属性赋值的对象,所以叫半成品嘛,先暂时完成赋值操作,这样,属性填充阶段就搞定了,剩下的初始化阶段就不用说了,循环依赖不就解决了吗?
好,那么也就是说,当A完成实例化,就会放到半成品中,这样A下的属性B在进行赋值的时候,因为也是要走那三个阶段的嘛,所以走到属性填充,它会去那三个Map中找,找到我说的那个半成品Map中发现找到了,就进行赋值操作,然后初始化,整个完成后,说明B走完了它的生命周期,就会被放到单例池中,也就是所谓的一级缓存。好,说到了一级,二级,那不是还有三级吗,那三级又是怎么回事呢?其实这跟AOP代理有关系了,也就是说,二级缓存里存的是对象的本身,并不是代理对象,那么代理是在什么时候产生的呢?答案是在初始化的时候产生的,说到这,就要说下BeanPostProcessors后置处理器了,这个后置处理器是可以在初始化前后进行调用,其中要说的是其的一个实现类,叫AspectJAwareAdvisorAutoProxyCreator,看到Proxy了没有,是不是代理的意思,不用说,该类肯定跟代理有关。但注意,正常情况下,代理是在初始化之后才执行的,但是如果在属性赋值的时候,因为要赋的是个代理,所以在实例化的这个阶段就会把代理提前,很难懂是吧,没事,先从getSingleton(beanName);开始,或者我们从一个案例说起,比如有以下案例,如下:
maven坐标:
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>
A类:
package com.cht.loop;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class A implements BeanFactoryAware {
//private String a;
@Autowired
private B b;
private BeanFactory beanFactory;
public void getBClass(){
System.out.println(b.getClass());
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException{
this.beanFactory = beanFactory;
}
}
B类:
package com.cht.loop;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class B {
@Autowired
private A a;
public void getAClass(){
System.out.println(a.getClass());
}
}
MyAspect类:
package com.cht.loop;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;
@Configuration
@ComponentScan(basePackages = "com.cht.loop")
@Component
@Aspect
//开启AspectJ 自动代理模式,如果不填proxyTargetClass=true,默认为false,
@EnableAspectJAutoProxy(proxyTargetClass=true)
public class MyAspect {
@Pointcut("execution(public void com.cht.loop.B.getAClass())")
public void hello(){
}
@Before("hello()")
public void qian(){
System.out.println("前置通知");
}
@After("hello()")
public void houzhi(){
System.out.println("后置通知");
}
}
Test类:
package com.cht.loop;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyAspect.class);
A a = (A) context.getBean("a");
a.getBClass(); //充分说明A类下的属性b注入的对象是其B类的代理对象
System.out.println("=====================");
B b = (B) context.getBean("b");
b.getAClass();//因为B中的getAClass方法被代理了,所以会有通知自动织入
}
}
注意看以上注释。结果如下:
class com.cht.loop.B$$EnhancerBySpringCGLIB$$bf47c568
=====================
前置通知
class com.cht.loop.A
后置通知
看Test类,把断点打到第8行,跟随我进入源码,一直到getBean那里,如下:
进入,到doGetBean方法,doGetBean方法前面已经粘贴出来了,这里就不重复粘贴,好,transformedBeanName(name);已经说过了,看getSingleton(beanName),让我们进入看看它是怎么获取的,如下:
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
继续:
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Quick check for existing instance without full singleton lock
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
synchronized (this.singletonObjects) {
// Consistent creation of early reference within full singleton lock
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
看如上代码的第3行,singletonObjects是指代谁,不用说,Ctrl+鼠标定位,可以看出就是我前面所说的一级缓存Map,也就是说,它一开始就从一级缓存中找,看看有没有beanName为a的A对象,很明显,第一次是没有的,我们还没往singletonObjects这个Map去put呢,所以,此时singletonObjects为null,没问题吧,好,看第四行的第二个条件isSingletonCurrentlyInCreation,什么意思,点进去看看,如下:
public boolean isSingletonCurrentlyInCreation(String beanName) {
return this.singletonsCurrentlyInCreation.contains(beanName);
}
就是看singletonsCurrentlyInCreation这个集合是否包含beanName,到此为止,我们都没往singletonsCurrentlyInCreation加入半点东西,所以为false,那么整体就不成立,跳到第24行,return一个singletonObject出去,是不是就是return一个null出去呀!好,继续看doGetBean方法,此时sharedInstance为null,没问题吧,好,看doGetBean方法的第10行,第一个条件就已经不成立了,而第二个条件的args默认就为null,所以为true,但又因为是&&的关系,所以整体为false,进入else里,好,跟随我走到else里,我跟随debug,此时你就会看到如下判断,我把它抽离出来,如下:
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
isPrototypeCurrentlyInCreation怎么跟isSingletonCurrentlyInCreation有点像,区别在于一个是Prototype,原型的,一个是Singleton,单例的,那么什么情况下为true,也就是抛出BeanCurrentlyInCreationException异常?就是当A类和B类都是原型Bean的时候,也就是两者都加上@Scope(“prototype”)的时候,就会抛出BeanCurrentlyInCreationException异常,也就是对于原型模式的循环依赖则是抛出BeanCurrentlyInCreationException异常,换句话说,循环依赖不支持原型Bean之间的依赖。继续往下看,getParentBeanFactory就不用说了,看名字应该是获取父工厂的bean,记得前面在开胃菜那节我提HierarchicalBeanFactory的时候类似,当然,此案例是没有的,跳过,看第85行,就是mbd.isSingleton()是true还是false,mbd理解成是A的BeanDefinition,很明显,A是单例的,所以为true,进入,下面就是一个Lambda表达式,我把它抽离出来,如下:
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
我们先进入getSingleton(String beanName, ObjectFactory<?> singletonFactory)方法,如下:
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
...
...
beforeSingletonCreation(beanName);
boolean newSingleton = false;
...
...
singletonObject = singletonFactory.getObject();
newSingleton = true;
...
...
afterSingletonCreation(beanName);
...
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
注意以上所在的类,也就是doGetBean,有两个getSingleton方法,要区分看参数,像第一个getSingleton就是在缓存中查找有没有这个bean,有就返回,没有就返回null。第二个getSingleton是在第一个getSingleton返回null的前提下进行的,目的就是创建一个Bean,并放到缓存中。如下:看如上方法的第4行,this.singletonObjects.get(beanName);,一样,会先去一级缓存找有没有key为a的记录,答案肯定是没有的,自始至终,我还没往singletonObjects添加一点东西,所以第5行singletonObject == null为true,成立,进入,到第8行,进入beforeSingletonCreation(beanName);,如下:
protected void beforeSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
看第二个条件,singletonsCurrentlyInCreation前面是不是见过了呀,注意它是set,那么如下:
也就是说,this.singletonsCurrentlyInCreation.add(beanName)中要add的beanName如果之前存在,就是false,不存在就是true,很明显,第一次,不存在,那么就是true,别忘了它还要取反,所以第二个条件就是false,又因为是&&的关系,所以整体为false,不会进入,当然就不会抛异常,知道第二个条件就行了。继续走getSingleton(String beanName, ObjectFactory<?> singletonFactory)方法,看第13行,这行就是要来执行createBean咯,也就是我前面说的Lambda表达式下的那个return createBean(beanName, mbd, args);,好,跟进去,看看它是怎么创建A这个Bean的,如下:
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
...
...
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
...
...
}
进入doCreateBean方法,如下:
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
...
instanceWrapper = createBeanInstance(beanName, mbd, args);
Object bean = instanceWrapper.getWrappedInstance();
...
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
...
...
return exposedObject;
}
看第4,5行,如下:

可以看出,是实例化好了A实例,底层用的是反射,其中应该会有推断构造方法的存在。但属性b还没赋值,是个空实例。
再看第7行,有三个条件,如下:
mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName)
第一个条件为true,第三个条件也为true,主要看第二个条件,翻译过来是是否允许循环引用,默认是支持的,我们可以看点过去,如下:
private boolean allowCircularReferences = true;
三个条件都为true,所以earlySingletonExposure就为true,看第14行,这行意思是提前暴露SingletonFactory对象,也就是所谓的三级缓存,如果我们把allowCircularReferences设置为false,那不好意思,提前暴露失效,那为什么要提前暴露,那是因为代理是在初始化后才生成的代理,但是当别的类要依赖我的时候(属性填充阶段),我得注入一个代理类进去,没事,我们还是进去吧,如下:
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
我们可以看出,它会去看看singletonObjects这个Map有没有beanName为a,如果没,就给它put一个,key就为a,value就是那个Lambda表达式,有什么用,后面说,继续往下走,看第18行,exposedObject就为原始Bean,然后看第20行,开始来填充属性了,填充完如下:

可以看到b属性赋值了,在赋值过程中肯定会去getBean(‘a’)的,因为循环依赖嘛,而beanFactory却为null,那是因为它是aware回调,我们再继续往下看,如下:
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
...
invokeAwareMethods(beanName, bean);
...
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
...
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
以上的invokeAwareMethods就是调用那些实现了xxxAware接口的类的,属于填充属性的一种。只要invokeAwareMethods(beanName, bean);执行完,如下:
beanFactory不就有值了吗。applyBeanPostProcessorsBeforeInitialization和applyBeanPostProcessorsAfterInitialization(里面会遍历所有BeanPostProcessors后置处理器,如果有一个返回null,将不会继续遍历下去。然后我说下BeanPostProcessors可以干什么事,比如它可以完成属性赋值,例如给实现了ApplicationContextAware接口的ApplicationContext属性赋值,还有像@Autowired、@Value等等),也就是BeanPostProcessors,它们俩把invokeInitMethods包围起来了,这里的invokeInitMethods就是调用初始化方法,比如我们在spring学过的那些被@PostConstruct标注的方法,还有实现了InitializingBean接口的afterPropertiesSet方法都是初始化方法。注意我前面提到过的代理正常就是在applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);这个阶段完成的,可以了解一下Bean的生命周期。那么最终被return的Bean就是被包装的Bean,赋给doCreateBean方法下的exposedObject,一套流程下来,可知doCreateBean方法完成了Bean的生命周期,比如实例化,填充属性,初始化。那么既然走完了这三个阶段,返回出去的Bean就是一个完整的Bean,完整的Bean我们应该放到一级缓存了,让我们回到getSingleton(String beanName, ObjectFactory<?> singletonFactory)方法,看第13行,singletonObject这时候就是一个完整的对象,然后第14行是不是为newSingleton赋一个true呀,再看第17行,afterSingletonCreation(beanName);,与前面的beforeSingletonCreation(beanName);相对应,进入,如下:
protected void afterSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}
看第2个条件,!this.singletonsCurrentlyInCreation.remove(beanName),是不是在进行删除操作呀,此时的beanName是不是为a,singletonsCurrentlyInCreation有没有这个a,当然有,因为那三个阶段结束了,就要把当前正在创建的标记去掉,所以开始remove,删除成功,为true,取反为false,所以以上条件不成立,不会抛出异常。继续看第19行,条件为true不用说,进入,开始addSingleton(beanName, singletonObject);,进入,如下:
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
singletonObjects代表一级缓存,是不是往一级缓存put了呀,然后如果三级缓存和二级缓存有beanName为a的去除掉,也就是说三个缓存只需要保存一个相同的beanName。好,回到getSingleton(String beanName, ObjectFactory<?> singletonFactory)的第23行,return一个完整的对象出去,让我们回到doGetBean方法,后面就不说了,感觉自己也说不清,先这样吧,让我们继续回退,回退到preInstantiateSingletons方法,方法有点多,大家自己跟着debug走,好,定位到第40行,找不到preInstantiateSingletons方法,用ctrl+F去查找,把preInstantiateSingletons粘贴上去,回车就行了,确实,文章写的有点多,好,到如下代码:

好,看if (singletonInstance instanceof SmartInitializingSingleton) {,为false,那么怎么为true,很简单,实现它,那么我们就再写一个类吧,如下:
package com.cht.loop;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.stereotype.Component;
@Component
public class C implements SmartInitializingSingleton {
//是在所有单例bean都已经被创建后执行的
@Override
public void afterSingletonsInstantiated() {
System.out.println("emem...");
}
}
这时候我们在测试,走到c类的时候,if (singletonInstance instanceof SmartInitializingSingleton) {就为true了,那么就会调用afterSingletonsInstantiated方法。至于该方法在Spring的用法,可以参考下@EventListener注解,看一下它的源码。
看preInstantiateSingletons方法的第14行,也就是if (isFactoryBean(beanName)) {,这个还没说呢,之前都是false的,直接跳到else里去getBean,那么现在我们就让它为true,进入,我把它抽离出来,如下:
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(
(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
看第2行,FACTORY_BEAN_PREFIX 代表谁,如下:
String FACTORY_BEAN_PREFIX = "&";
然后注意第2行是不是进行了getBean操作了呀,也就是getBean(&beanName),得到的bean应该是它本身,而不是getObject返回的对象,以DServiceBean类为例,DServiceBean构造方法就被调用了,但是注意getObject返回的对象并没有被调用,然后我们往下看,是不是还有一个getBean操作,行,我们继续往下走,看看getObject返回的对象有没有被调用,只要它经过getBean就行,第3行,肯定为true,进入,看第6行的第2个条件,也就是factory instanceof SmartFactoryBean,不用讲,为false,因为我们没有实现SmartFactoryBean,所以进入else里,第一个条件依然不成立,所以isEagerInit 为false,为false下面我们就不能去getBean咯!那我们去实现SmartFactoryBean吧,如下:
package com.cht.services;
import org.springframework.beans.factory.SmartFactoryBean;
import org.springframework.stereotype.Service;
@Service
public class DServiceBean implements SmartFactoryBean<DService> {
public DServiceBean(){
System.out.println("DServiceBean被调用");
}
@Override
public DService getObject() throws Exception {
return new DService();
}
@Override
public Class<?> getObjectType() {
return DService.class;
}
@Override
public boolean isSingleton() {
return true;
}
@Override
public boolean isEagerInit() {
return true;
}
}
走到源码当中,最终它走到else里,也就是第11行到第14行,第一个条件成立,第二个条件是不是调用了isEagerInit()方法,是不是返回true,为true的话isEagerInit就为true,那么到第15行,不就成立了吗,成立了,下一步不就getBean(beanName)了吗,所以DServiceBean类下的getObject方法返回的DService对象的构造方法不就被调用了吗,这就是SmartFactoryBean的作用,也就是说,默认是不会去实例化getObject返回的对象的。
接着,我们把剩下的循环依赖讲完吧,就是我们在走A类的生命周期的时候,走到了填充属性populateBean那里,是不是要填充一个B对象进来呀,那好,我们默认在populateBean方法里它进行了getBean(‘b’)的操作,行,那我们开始去getBean一个b,流程如下:
- 去缓存中看看有没有key为b的记录,并且看它是否标记为正在创建中,如果有,就返回,否则看b是否正在创建中,第一次肯定没有,没有就返回一个null出去。
- 判断B是否为单例,如果是,再一次从缓存中再找一遍,找到就返回,找不到,行,开始给它打上正在创建的标记,进入createBean中,开始创建。
- 进入了createBean中,开始进行B类的实例化,实例化好但此时属性还没赋值,那么开始填充属性,但在填充属性之前要看看它是否支持循环依赖,默认是支持的,所以,实例化好后进行暴露工厂对象,说白了,就是往第三个Map中put一条记录,key就是b,value就是ObjectFactory对象。
- 暴露好后,进行填充属性,发现要填充一个A对象,好,进行getBean(‘a’),getBean第一步是不是要去缓存中找呀,具体应该是先从一级缓存中找,找不到,正常,因为A类还没走完它的生命周期呢,正在填充属性这关卡着呢,而我前面也说了一级缓存存放的对象是完整的对象,完整的对象什么意思我也说过了。
- 但别忘了,A类还在创建中,所以,它就会去二级缓存中找有没有key为a的对象,如果没有,就去第三个Map中找,也就是singletonFactories这个Map,而你别忘了,在A类要填充属性之前也一样暴露了singletonFactories这个Map,key就是a,所以,这次它能获取到a对象,注意是a的代理,如果没设置代理,那还是a的本身,拿到后,就把singletonFactories这个Map中的key为a的去除掉,移到二级缓存也就是earlySingletonObjects中,因为拿到了A对象,所以完成属性赋值。
- 接着B类走初始化阶段,后置处理阶段,整个走完之后,B类也就是一个完整对象了,这时候,就可以把B类身上的正在创建的标记去掉,然后放到一级缓存这个Map中。
- 下面A类下的属性B也就填充完了,继续走A的初始化过程,并添加到一级缓存中,再把二级缓存中的key为a的删除掉。
本文深入剖析 Spring 框架中 Bean 的生命周期管理机制,包括 Bean 定义的注册、依赖注入及初始化过程等内容。
476

被折叠的 条评论
为什么被折叠?



