Spring ioc源码(V1.0)

本文深入剖析 Spring 框架中 Bean 的生命周期管理机制,包括 Bean 定义的注册、依赖注入及初始化过程等内容。
摘要由CSDN通过智能技术生成

 本文章是我耗时三天多的时间完成的,由于时间的限制,再加上自己能力有限,所以本文章难免会有不足之处,同时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,流程如下:

  1. 去缓存中看看有没有key为b的记录,并且看它是否标记为正在创建中,如果有,就返回,否则看b是否正在创建中,第一次肯定没有,没有就返回一个null出去。
  2. 判断B是否为单例,如果是,再一次从缓存中再找一遍,找到就返回,找不到,行,开始给它打上正在创建的标记,进入createBean中,开始创建。
  3. 进入了createBean中,开始进行B类的实例化,实例化好但此时属性还没赋值,那么开始填充属性,但在填充属性之前要看看它是否支持循环依赖,默认是支持的,所以,实例化好后进行暴露工厂对象,说白了,就是往第三个Map中put一条记录,key就是b,value就是ObjectFactory对象。
  4. 暴露好后,进行填充属性,发现要填充一个A对象,好,进行getBean(‘a’),getBean第一步是不是要去缓存中找呀,具体应该是先从一级缓存中找,找不到,正常,因为A类还没走完它的生命周期呢,正在填充属性这关卡着呢,而我前面也说了一级缓存存放的对象是完整的对象,完整的对象什么意思我也说过了。
  5. 但别忘了,A类还在创建中,所以,它就会去二级缓存中找有没有key为a的对象,如果没有,就去第三个Map中找,也就是singletonFactories这个Map,而你别忘了,在A类要填充属性之前也一样暴露了singletonFactories这个Map,key就是a,所以,这次它能获取到a对象,注意是a的代理,如果没设置代理,那还是a的本身,拿到后,就把singletonFactories这个Map中的key为a的去除掉,移到二级缓存也就是earlySingletonObjects中,因为拿到了A对象,所以完成属性赋值。
  6. 接着B类走初始化阶段,后置处理阶段,整个走完之后,B类也就是一个完整对象了,这时候,就可以把B类身上的正在创建的标记去掉,然后放到一级缓存这个Map中。
  7. 下面A类下的属性B也就填充完了,继续走A的初始化过程,并添加到一级缓存中,再把二级缓存中的key为a的删除掉。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值