Spring依赖注入(DI)之注解形式

目录

1.前言

2.使用注解实现依赖注入

3. 依赖注入相关的注解

3.1 为什么会需要使用这些注解?

3.2 相关的注解

3.2.1 类的定义注解

3.2.2 注入相关的注解

4. 源码分析

4.1 初始化过程

4.2 Bean的获取

4.3 Autowired的工作原理

4.4 如果确保被自动装配的对象在装配时已经完成初始化?

4.5 如果解决循环依赖问题


1.前言

上一篇文章中《Spring 控制反转(IOC)及依赖注入(DI)》https://blog.csdn.net/luofen521/article/details/120273369介绍了Spring 中IOC及DI的一些概念,并主要分析了XML形式setter方式注入的源码,这篇文章主要介绍使用@Autowired注解字段注入的方式来实现依赖注入的源码。

2.使用注解实现依赖注入

首先我们定义一个StudentDao,用于模拟操作数据库的操作接口,定义了getStudent方法,如下:

public interface StudentDao {
    Student getStudent();
}

然后我们创建一个实现类StudentDaoImpl,在getStudent方法模拟了从数据库获取数据的操作,并在接口的定义加上@Repository注解,如下:

@Repository
public class StudentDaoImpl implements StudentDao {

    @Override
    public Student getStudent() {
        Student student = new Student();
        student.setId(24);
        student.setName("zhangsan");
        return student;
    }
}

Dao层好了,我们现在来定义Service层

首先,创建一个SudentService接口,并定义了getStudent方法,如下:

public interface StudentService {
    Student getStudent();
}

然后创建一个实现类StudentServiceImpl,在类的定义上加上@Service注解,并引入了StudentDao,用于调用Dao层的方法,在定义StudentDao时加上了@Resource注解,代码如下:

@Service
public class StudentServiceImpl implements StudentService{

    @Resource
    StudentDao studentDao;

    @Override
    public Student getStudent() {
        return studentDao.getStudent();
    }
}

到此,Service层也定义好了,我们在测试单元中去验证下,首先也是定义了StudentService ,并在定义上面加上了@Resource注解,然后调用其getStudent方法,代码如下:

@SpringBootTest
class ApplicationTests {

    @Resource
    StudentService studentService;

    @Test
    void contextLoads() {
        Student student = studentService.getStudent();
        System.out.println("学生id:" + student.getId());
        System.out.println("学生姓名:" + student.getName());
    }
}

运行结果如下:

 可以看到,我们没有手动地去创建Servcie、Dao层对应类的对象,而是通过@Repository、@Service、@Resource等注解完成了Bean的创建和关联。

接下来我们看看这些注解的含义

3. 依赖注入相关的注解

3.1 为什么会需要使用这些注解?

在Spring早期的版本,是使用配置文件来管理bean的定义,当项目越来越复杂时,配置文件的管理成了一个很艰巨的任务,如下:

<?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 http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="book" class="Book" scope="singleton">
        <property name="bookName" value="平凡的世界"/>
        <property name="author" value="路遥"/>
    </bean>
    <bean id="book2" class="Book2" scope="prototype">
        <property name="bookName" value="平凡的世界"/>
        <property name="author" value="路遥"/>
    </bean>
    <bean id="bookService" class="BookService">
        <property name="book" ref="book" />
    </bean>
</beans>

所以在Spring后面的版本,逐渐引入了注解来标识哪些类需要由Spring容器来管理,这样做主要是为了管理方便。

看下面这样,是不是要简单得多?

@Service
public class StudentServiceImpl implements StudentService {

}

3.2 相关的注解

3.2.1 类的定义注解

其实除了上述用到的Service、Repository注解,还有@Controller、@Component也是常用的注解,它们用于定义类时标识类对象的创建有Spring来统一管理,我们先来看看他们的定义

@Controller

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {

	/**
	 * The value may indicate a suggestion for a logical component name,
	 * to be turned into a Spring bean in case of an autodetected component.
	 * @return the suggested component name, if any (or empty String otherwise)
	 */
	@AliasFor(annotation = Component.class)
	String value() default "";

}

@Service

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Service {

	/**
	 * The value may indicate a suggestion for a logical component name,
	 * to be turned into a Spring bean in case of an autodetected component.
	 * @return the suggested component name, if any (or empty String otherwise)
	 */
	@AliasFor(annotation = Component.class)
	String value() default "";

}

@Repository

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Repository {

	/**
	 * The value may indicate a suggestion for a logical component name,
	 * to be turned into a Spring bean in case of an autodetected component.
	 * @return the suggested component name, if any (or empty String otherwise)
	 */
	@AliasFor(annotation = Component.class)
	String value() default "";

}

会发现@Controller、@Service、@Repository除了名字不同,实现一模一样,并且定义上都使用了 @Component注解。

所以可以这么理解,@Controller、@Service、@Repository =( @Component + 特定的功能),但他们在依赖注入这方面的功能是一样的。

@RestController

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
    @AliasFor(
        annotation = Controller.class
    )
    String value() default "";
}

而RestController结合了@Controller和@ReponseBody,不需要再在方法的返回上加@ReponseBody,下面是@Controller和@RestController的对比

@Controller

@Controller
@RequestMapping("books")
public class SimpleBookController {

    @GetMapping("/{id}", produces = "application/json")
    public @ResponseBody Book getBook(@PathVariable int id) {
        return findBookById(id);
    }

    private Book findBookById(int id) {
        // ...
    }
}

@RestController 

@RestController
@RequestMapping("books-rest")
public class SimpleBookRestController {
    
    @GetMapping("/{id}", produces = "application/json")
    public Book getBook(@PathVariable int id) {
        return findBookById(id);
    }

    private Book findBookById(int id) {
        // ...
    }
}

总结如下:

序号注解含义
1@Component通用的注解,可以定义Spring管理的任务组件
2@Controller用于表现层(spring-mvc中使用),具有转发、重定向等特性
3@Service用于业务逻辑层
4@Repository用于持久层,并自动处理数据库操作产生的异常
5@RestControler用于表现层,集合了@Controller和@ReponseBody的特性

上述主要是类定义时,用到的注解,定义好之后,我们还需要在使用的地方使用引用的注解。

3.2.2 注入相关的注解

上述用到了@Resource注解来把我们需要的对象进行注入,其实常用的还有@Autowired

在上述的代码中,我们使用@Autowired来代替@Resource也是可以的,代码如下:

@Service
public class StudentServiceImpl implements StudentService{

    @Autowired
    StudentDao studentDao;

    @Override
    public Student getStudent() {
        return studentDao.getStudent();
    }
}

那@Resouce和@Autowired有什么区别呢?

首先,我们看看他们的定义,可以看到Resource是java自带的属性;而Autowired是springframework提供的注解

package javax.annotation;
public @interface Resource {



package org.springframework.beans.factory.annotation;

public @interface Autowired {

其次,@Autowired是根据类型来装配依赖对象,但是如果我们同一个类型有多个对象会怎么样?比如我们把上面的StudentDaoImpl类再复制一个放到新建的dao文件夹下,这时候就会有有2个类型为StudentDaoImpl的类,这时候我们运行程序就会报下面的错误:

Caused by: org.springframework.beans.factory.BeanDefinitionStoreException: 
Failed to parse configuration class [com.yc.springboot.Application]; nested exception is org.springframework.context.annotation.ConflictingBeanDefinitionException: 
Annotation-specified bean name 'studentDaoImpl' for bean class [com.yc.springboot.dao.StudentDaoImpl] 
conflicts with existing, non-compatible bean definition of same name and class [com.yc.springboot.StudentDaoImpl]

	... 63 more

可以看到,在装配StudentDao时,发现有两个相同类型的实现类,所以报错了,这个时候就需要用到@Qualifier注解。首先,我们在dao下的StudentDaoImpl中写value值“StudentDaoImpl2 ”,并设置name为“zhangsan 2”,代码如下:

package com.yc.springboot.dao;


import com.yc.springboot.Student;
import com.yc.springboot.StudentDao;
import org.springframework.stereotype.Repository;

@Repository("StudentDaoImpl2")
public class StudentDaoImpl implements StudentDao {

    @Override
    public Student getStudent() {
        Student student = new Student();
        student.setId(24);
        student.setName("zhangsan 2");
        return student;
    }
}

然后在StudentServiceImpl中引入时,用@Qualifier("StudentDaoImpl2")来指定我们希望装配的对象,如下:

@Service
public class StudentServiceImpl implements StudentService{

    @Autowired
    @Qualifier("StudentDaoImpl2")
    StudentDao studentDao;

    @Override
    public Student getStudent() {
        return studentDao.getStudent();
    }
}

运行结果如下,可以看到,这个时候打印出来的名字为“zhangsan 2”,也就是说我们通过@Qualifier和@Autowired搭配使用,实现了按name来装配的效果

 而@Resource默认就是byName来自动装配,我们还是用之前的StudentDaoImpl2来举例,我们可以直接在定义时,给@Resource制定name为“StudentDaoImpl2”,如下:

@Service
public class StudentServiceImpl implements StudentService{
    @Resource(name="StudentDaoImpl2")
    StudentDao studentDao;

    @Override
    public Student getStudent() {
        return studentDao.getStudent();
    }
}

运行结果跟使用@Qualifier和@Autowired搭配使用是一致的。

其实,@Resource支持按照byName来装配的,也支持通过type来按照byType来装配,如下:

@Service
public class StudentServiceImpl implements StudentService{

    @Resource(type = StudentDaoImpl.class)
    StudentDao studentDao;

    @Override
    public Student getStudent() {
        return studentDao.getStudent();
    }
}

4. 源码分析

我们接下来看看源码,是怎么实现的

首先,我们要创建一个AppConfig作为配置文件,并增加注解@ComponentScan用于指定需要进行组件扫描的包

@Configuration
@ComponentScan("com.yc.springframework")
public class AppConfig {
}

然后在我们的测试类中,去初始化ioc容器,然后获取StudentService,并调用其方法

public class IOCAnnotatedTest {

    public static void main(String[] args) {
        //初始化IOC容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
        //获取bean
        StudentService studentService = applicationContext.getBean(StudentService.class);
        //调用bean的方法
        Student student = studentService.getStudent();
        System.out.println("学生id:" + student.getId());
        System.out.println("学生姓名:" + student.getName());
    }
}

而在StudentServiceImpl的定义中,使用了@Service声明,并使用@Autowired来自动装配StudentDao对象,如下:

@Service
public class StudentServiceImpl implements StudentService {

    @Autowired
    StudentDao studentDao;

    @Override
    public Student getStudent() {
        return studentDao.getStudent();
    }
}

4.1 初始化过程

首先是通过下面这行代码完成了IOC容器的初始化

        //初始化IOC容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);

构造方法如下所示

	public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
		this();
		register(annotatedClasses);
		refresh();
	}

看起来是不是跟xml实现依赖注入的方式很像,这里主要还是看refresh方法

	@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
                //省略部分代码...

			try {
				

				//调用这个上下文中注册为bean的工厂处理器
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				initMessageSource();

				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				onRefresh();

				// Check for listener beans and register them.
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				finishRefresh();
			}

			catch (BeansException ex) {
	            //删除无关代码
			}

			finally {
				resetCommonCaches();
			}
		}
	}

最后会调用到PostProcessorRegistrationDelegate的invokeBeanFactoryPostProcessors方法


	public static void invokeBeanFactoryPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
            //省略部分代码

			// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
			String[] postProcessorNames =
					beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
				}
			}
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);
            //调用BeanDefinition注册处理器
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            
            //省略部分代码...


	}

调用了invokeBeanDefinitionRegistryPostProcessors方法,代码如下:

	private static void invokeBeanDefinitionRegistryPostProcessors(
			Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {

		for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
			postProcessor.postProcessBeanDefinitionRegistry(registry);
		}
	}

这里其实是调用了ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法,如下:

	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
		int registryId = System.identityHashCode(registry);
		if (this.registriesPostProcessed.contains(registryId)) {
			throw new IllegalStateException(
					"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
		}
		if (this.factoriesPostProcessed.contains(registryId)) {
			throw new IllegalStateException(
					"postProcessBeanFactory already called on this post-processor against " + registry);
		}
		this.registriesPostProcessed.add(registryId);

		processConfigBeanDefinitions(registry);
	}

 主要是调用了processConfigBeanDefinitions方法对配置进行了解析,代码如下:

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
		List<BeanDefinitionHolder> configCandidates = new ArrayList<BeanDefinitionHolder>();
		String[] candidateNames = registry.getBeanDefinitionNames();


		// Parse each @Configuration class
		ConfigurationClassParser parser = new ConfigurationClassParser(
				this.metadataReaderFactory, this.problemReporter, this.environment,
				this.resourceLoader, this.componentScanBeanNameGenerator, registry);

		Set<BeanDefinitionHolder> candidates = new LinkedHashSet<BeanDefinitionHolder>(configCandidates);
		Set<ConfigurationClass> alreadyParsed = new HashSet<ConfigurationClass>(configCandidates.size());
		do {
            //对候选者进行解析
			parser.parse(candidates);
			parser.validate();

			Set<ConfigurationClass> configClasses = new LinkedHashSet<ConfigurationClass>(parser.getConfigurationClasses());
			configClasses.removeAll(alreadyParsed);

			// Read the model and create bean definitions based on its content
			if (this.reader == null) {
				this.reader = new ConfigurationClassBeanDefinitionReader(
						registry, this.sourceExtractor, this.resourceLoader, this.environment,
						this.importBeanNameGenerator, parser.getImportRegistry());
			}
			this.reader.loadBeanDefinitions(configClasses);
			alreadyParsed.addAll(configClasses);

			candidates.clear();
			if (registry.getBeanDefinitionCount() > candidateNames.length) {
				String[] newCandidateNames = registry.getBeanDefinitionNames();
				Set<String> oldCandidateNames = new HashSet<String>(Arrays.asList(candidateNames));
				Set<String> alreadyParsedClasses = new HashSet<String>();
				for (ConfigurationClass configurationClass : alreadyParsed) {
					alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
				}
				for (String candidateName : newCandidateNames) {
					if (!oldCandidateNames.contains(candidateName)) {
						BeanDefinition bd = registry.getBeanDefinition(candidateName);
						if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
								!alreadyParsedClasses.contains(bd.getBeanClassName())) {
							candidates.add(new BeanDefinitionHolder(bd, candidateName));
						}
					}
				}
				candidateNames = newCandidateNames;
			}
		}
		while (!candidates.isEmpty());

		// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
		if (sbr != null) {
			if (!sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
				sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
			}
		}

		if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
			((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
		}
	}

首先是调用了ConfigurationClassParser的parse方法

	public void parse(Set<BeanDefinitionHolder> configCandidates) {
		this.deferredImportSelectors = new LinkedList<DeferredImportSelectorHolder>();

		for (BeanDefinitionHolder holder : configCandidates) {
			BeanDefinition bd = holder.getBeanDefinition();
			try {
				if (bd instanceof AnnotatedBeanDefinition) {
                    //对注解BeanDefinition进行解析
					parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
				}
				else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
					parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
				}
				else {
					parse(bd.getBeanClassName(), holder.getBeanName());
				}
			}
			catch (BeanDefinitionStoreException ex) {
				throw ex;
			}
			catch (Throwable ex) {
				throw new BeanDefinitionStoreException(
						"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
			}
		}

		processDeferredImportSelectors();
	}

这里会继续调用ConfigurationClassParser的parse方法

	protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
		processConfigurationClass(new ConfigurationClass(metadata, beanName));
	}

直接调用了同类中的processConfigurationClass方法

	protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
		

		// Recursively process the configuration class and its superclass hierarchy.
		SourceClass sourceClass = asSourceClass(configClass);
		do {
            //对于配置的class进行处理
			sourceClass = doProcessConfigurationClass(configClass, sourceClass);
		}
		while (sourceClass != null);

		this.configurationClasses.put(configClass, configClass);
	}

调用了doProcessConfigurationClass对配置类进行解析

	protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
			throws IOException {

		//省略了部分代码

		// Process any @ComponentScan annotations
		Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
				sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
		if (!componentScans.isEmpty() &&
				!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
			for (AnnotationAttributes componentScan : componentScans) {
				// The config class is annotated with @ComponentScan -> perform the scan immediately
				Set<BeanDefinitionHolder> scannedBeanDefinitions =
						this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
				// Check the set of scanned definitions for any further config classes and parse recursively if needed
				for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
					BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
					if (bdCand == null) {
						bdCand = holder.getBeanDefinition();
					}
					if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
						parse(bdCand.getBeanClassName(), holder.getBeanName());
					}
				}
			}
		}

		//省略部分代码...

		// No superclass -> processing is complete
		return null;
	}

这里会调用ComponentScanAnnotationParser的parse方法

	public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
		//省略部分代码
		return scanner.doScan(StringUtils.toStringArray(basePackages));
	}

实际上是调用了ClassPathBeanDefinitionScanner的doScan方法

	protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
		Assert.notEmpty(basePackages, "At least one base package must be specified");
		Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();
		for (String basePackage : basePackages) {
            //通过扫描basePackages得到需要的Bean定义
			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 (candidate instanceof AbstractBeanDefinition) {
					postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
				}
				if (candidate instanceof AnnotatedBeanDefinition) {
					AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
				}
				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;
	}
我们先看ClassPathScanningCandidateComponentProvider的findCandidateComponents选择候选的组件
	public Set<BeanDefinition> findCandidateComponents(String basePackage) {
		Set<BeanDefinition> candidates = new LinkedHashSet<BeanDefinition>();
		try {
			String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
					resolveBasePackage(basePackage) + '/' + this.resourcePattern;
            //得到packageScan路径下所有的类
			Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath);
			boolean traceEnabled = logger.isTraceEnabled();
			boolean debugEnabled = logger.isDebugEnabled();
			for (Resource resource : resources) {
				if (traceEnabled) {
					logger.trace("Scanning " + resource);
				}
				if (resource.isReadable()) {
					try {
						MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);
                        //判断是否为候选组件
						if (isCandidateComponent(metadataReader)) {
							ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
							sbd.setResource(resource);
							sbd.setSource(resource);
							if (isCandidateComponent(sbd)) {
                                //加入到BeanDefinition列表,作为bean的候选名单
								candidates.add(sbd);
							}
						}
                        //省略部分代码
					}
				}

			}
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
		}
		return candidates;
	}

得到我们需要加载的组件后,doScan方法中遍历了Set<BeanDefinition>,并调用了registerBeanDefinition方法,最后会调用到DefaultListableBeanFactory的registerBeanDefinition方法,具体如下:

	@Override
	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {

		
		BeanDefinition oldBeanDefinition;

		oldBeanDefinition = this.beanDefinitionMap.get(beanName);
		if (oldBeanDefinition != null) {
			//如果已经存在定义了,则日志输出警告
		}
		else {
			if (hasBeanCreationStarted()) {
				// Cannot modify startup-time collection elements anymore (for stable iteration)
				synchronized (this.beanDefinitionMap) {
                    //把定义存到Map中
					this.beanDefinitionMap.put(beanName, beanDefinition);
					List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);
					updatedDefinitions.addAll(this.beanDefinitionNames);
					updatedDefinitions.add(beanName);
					this.beanDefinitionNames = updatedDefinitions;
					if (this.manualSingletonNames.contains(beanName)) {
						Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);
						updatedSingletons.remove(beanName);
						this.manualSingletonNames = updatedSingletons;
					}
				}
			}
			else {
				// Still in startup registration phase
				this.beanDefinitionMap.put(beanName, beanDefinition);
				this.beanDefinitionNames.add(beanName);
				this.manualSingletonNames.remove(beanName);
			}
			this.frozenBeanDefinitionNames = null;
		}

		if (oldBeanDefinition != null || containsSingleton(beanName)) {
			resetBeanDefinition(beanName);
		}
	}

会发现这里会把BeanDefinition存到beanDefinitionMap中,看看它的定义

	private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);

它是一个ConcurrentHashMap对象,后面再创建Bean时,会从这个集合中获取需要创建的Bean

这个时候就完成了哪些类需要初始化的筛选,接下来要真正地来初始化Bean了,我们再回到AbstractApplicationContext类的refresh方法,其中下面这段代码是完成单例的初始化的

// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);

后面的流程,就跟之前xml实现依赖注入的流程一致了,就不做详细展开了。可以看上一篇文章。

可以看到使用注解和使用xml实现依赖注入的方式,只有在解析Bean定义的时候不同,后面的创建Bean及初始化流程是一致的。

4.2 Bean的获取

我们也是通过getBean方法获取Bean

  StudentService studentService = applicationContext.getBean(StudentService.class);
我们看看
	@Override
	public <T> T getBean(Class<T> requiredType) throws BeansException {
		assertBeanFactoryActive();
		return getBeanFactory().getBean(requiredType);
	}
这里调用的是DefaultListableBeanFactory的getBean方法
	@Override
	public <T> T getBean(Class<T> requiredType) throws BeansException {
		return getBean(requiredType, (Object[]) null);
	}

	@Override
	public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {
        //获取Bean的持有类
		NamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, args);
		if (namedBean != null) {
			return namedBean.getBeanInstance();
		}
		BeanFactory parent = getParentBeanFactory();
		if (parent != null) {
			return parent.getBean(requiredType, args);
		}
		throw new NoSuchBeanDefinitionException(requiredType);
	}

这里是直接调用了resolveNamedBean方法获取Bean的持有类

	@SuppressWarnings("unchecked")
	private <T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType, Object... args) throws BeansException {
        //省略部分代码...

		if (candidateNames.length == 1) {
			String beanName = candidateNames[0];
            //调用getBean方法获取Bean
			return new NamedBeanHolder<T>(beanName, getBean(beanName, requiredType, args));
		}
        
        //省略部分代码

		return null;
	}

这里调用了AbstractBeanFactory的getBean方法,这就回到了xml实现注解获取Bean的流程,就不详细展开介绍了。

4.3 Autowired的工作原理

我们StudentServiceImpl中的StudentDao是通过使用Autowired注解进行注入的,并增加一个Student 对象,但是不增加@Autowired注解,代码如下:

@Service
public class StudentServiceImpl implements StudentService {

    @Autowired
    StudentDao studentDao;

    Student student;


    @Override
    public Student getStudent() {
        return studentDao.getStudent();
    }
}

我们来看看Autowired是怎么工作的,我们需要回到创建Beand的地方AbstractAutowireCapableBeanFactory的doCreateBean方法中,代码如下:

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
			throws BeanCreationException {

		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
            //创建Bean
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
		Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
		mbd.resolvedTargetType = beanType;

		// 允许后置处理器来处理bean
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				try {
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				mbd.postProcessed = true;
			}
		}

	    //省略部分代码

		return exposedObject;
	}

我们可以看到主要是调用了applyMergedBeanDefinitionPostProcessors方法

	protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof MergedBeanDefinitionPostProcessor) {
				MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
				bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
			}
		}
	}

这里是把后置处理器都拿出来,然后处理bean,这里是调用的AutowiredAnnotationBeanPostProcessor的postProcessMergedBeanDefinition方法

	@Override
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
		if (beanType != null) {
            //找到自动注解的元数据
			InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
			metadata.checkConfigMembers(beanDefinition);
		}
	}

这里就是调用了findAutowiringMetadata方法去找到哪些需要自动注入的源数据

	private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, PropertyValues pvs) {
		// Fall back to class name as cache key, for backwards compatibility with custom callers.
		String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
		// Quick check on the concurrent map first, with minimal locking.
		InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
		if (InjectionMetadata.needsRefresh(metadata, clazz)) {
			synchronized (this.injectionMetadataCache) {
				metadata = this.injectionMetadataCache.get(cacheKey);
				if (InjectionMetadata.needsRefresh(metadata, clazz)) {
					if (metadata != null) {
						metadata.clear(pvs);
					}
					try {
                        //构建自动注入的元数据
						metadata = buildAutowiringMetadata(clazz);
						this.injectionMetadataCache.put(cacheKey, metadata);
					}
					catch (NoClassDefFoundError err) {
						throw new IllegalStateException("Failed to introspect bean class [" + clazz.getName() +
								"] for autowiring metadata: could not find class that it depends on", err);
					}
				}
			}
		}
		return metadata;
	}

这里主要是判断内存缓存中是否存在,不存在则调用buildAutowiringMetadata方法去构建,并且加入到缓存中,我们继续看buildAutowiringMetadata方法:

	private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
		LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<InjectionMetadata.InjectedElement>();
		Class<?> targetClass = clazz;

		do {
			final LinkedList<InjectionMetadata.InjectedElement> currElements =
					new LinkedList<InjectionMetadata.InjectedElement>();
            //处理带有注解的属性
			ReflectionUtils.doWithLocalFields(targetClass, new ReflectionUtils.FieldCallback() {
				@Override
				public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
                    //找到需要注入的属性
					AnnotationAttributes ann = findAutowiredAnnotation(field);
					if (ann != null) {
						if (Modifier.isStatic(field.getModifiers())) {
							if (logger.isWarnEnabled()) {
								logger.warn("Autowired annotation is not supported on static fields: " + field);
							}
							return;
						}
						boolean required = determineRequiredStatus(ann);
                        //主要注入的属性
						currElements.add(new AutowiredFieldElement(field, required));
					}
				}
			});
                
            //处理带有注解的方法
			ReflectionUtils.doWithLocalMethods(targetClass, new ReflectionUtils.MethodCallback() {
				@Override
				public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
					Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
					if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
						return;
					}
					AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
					if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
						if (Modifier.isStatic(method.getModifiers())) {
							if (logger.isWarnEnabled()) {
								logger.warn("Autowired annotation is not supported on static methods: " + method);
							}
							return;
						}
						if (method.getParameterTypes().length == 0) {
							if (logger.isWarnEnabled()) {
								logger.warn("Autowired annotation should only be used on methods with parameters: " +
										method);
							}
						}
						boolean required = determineRequiredStatus(ann);
						PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
						currElements.add(new AutowiredMethodElement(method, required, pd));
					}
				}
			});

			elements.addAll(0, currElements);
			targetClass = targetClass.getSuperclass();
		}
		while (targetClass != null && targetClass != Object.class);
        //构造一个InjectionMetadata返回,需要注入的元素在elements中
		return new InjectionMetadata(clazz, elements);
	}

先调用doWithLocalFields方法处理带有注解的属性

    public static void doWithLocalFields(Class<?> clazz, ReflectionUtils.FieldCallback fc) {
        //找到当前类中的属性
        Field[] var2 = getDeclaredFields(clazz);
        int var3 = var2.length;

        for(int var4 = 0; var4 < var3; ++var4) {
            Field field = var2[var4];

            try {
                //回调doWith方法,对每个属性进行处理
                fc.doWith(field);
            } catch (IllegalAccessException var7) {
                throw new IllegalStateException("Not allowed to access field '" + field.getName() + "': " + var7);
            }
        }

    }

我们继续看回调的doWith方法

			ReflectionUtils.doWithLocalFields(targetClass, new ReflectionUtils.FieldCallback() {
				@Override
				public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
                    //找到属性上带的注解
					AnnotationAttributes ann = findAutowiredAnnotation(field);
					if (ann != null) {
						if (Modifier.isStatic(field.getModifiers())) {
							if (logger.isWarnEnabled()) {
								logger.warn("Autowired annotation is not supported on static fields: " + field);
							}
							return;
						}
						boolean required = determineRequiredStatus(ann);
                        //如果不为null,则加入到elements中
						currElements.add(new AutowiredFieldElement(field, required));
					}
				}
			});

先调用findAutowiredAnnotation方法得到当前属性上的注解,如果我们带有@Autowired、@Value,则会获取到对应的值;如果没有注解,则为null;当有值时,把属性当做参数,构造一个AutowiredFieldElement对象存入到elements中

下面是对带有注解的方法的处理,流程跟带有属性带有注解类似就不做解释了,然后再把得到的通过构造一个InjectionMetadata对象返回,这个对象里带有了那些属性需要自动注入,这样就完成了当前类中的哪些属性需要自动注入,我们在AutowiredAnnotationBeanPostProcessor类的findAutowiringMetadata方法中buildAutowiringMetadata处增加断点,我们单步调试:

 可以看到,需要注解的元数据包含了增加了@Autowired的studentDao,但是不包含没有注解的Book对象

这样就完成了查找当前对象中哪些属性是需要自动注入的,但是具体什么时候注入的呢?我们继续往下看,我们回到AbstractAutowireCapableBeanFactory类中的doCreateBean方法,在调用createBeanInstance方法创建实例、applyMergedBeanDefinitionPostProcessors方法找到哪些需要自动注入的属性后,然后调用populateBean方法进行对象的初始化

protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
		PropertyValues pvs = mbd.getPropertyValues();

		//省略部分代码

		if (hasInstAwareBpps || needsDepCheck) {
			PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
			if (hasInstAwareBpps) {
                //遍历后置处理器
				for (BeanPostProcessor bp : getBeanPostProcessors()) {
					if (bp instanceof InstantiationAwareBeanPostProcessor) {
						InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                        //给属性赋值
						pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
						if (pvs == null) {
							return;
						}
					}
				}
			}
			if (needsDepCheck) {
				checkDependencies(beanName, mbd, filteredPds, pvs);
			}
		}

		applyPropertyValues(beanName, mbd, bw, pvs);
	}

我们来看下AutowiredAnnotationBeanPostProcessor的postProcessPropertyValues方法,如下:

	@Override
	public PropertyValues postProcessPropertyValues(
			PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
        //获取需要自动注入的属性
		InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
		try {
            //完成自动注入
			metadata.inject(bean, beanName, pvs);
		}
		catch (BeanCreationException ex) {
			throw ex;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
		}
		return pvs;
	}

findAutowiringMetadata方法就是通过beanName从缓存中获取到需要自动装配的属性,而在之前的流程我们说到了如果查找到需要自动注入的属性,并且把它们放到了缓存中。拿StudentServiceImpl对象的创建为例,这里是studentDao,然后调用InjectionMetadata的inject方法,如下:

	public void inject(Object target, String beanName, PropertyValues pvs) throws Throwable {
		Collection<InjectedElement> elementsToIterate =
				(this.checkedElements != null ? this.checkedElements : this.injectedElements);
		if (!elementsToIterate.isEmpty()) {
			boolean debug = logger.isDebugEnabled();
			for (InjectedElement element : elementsToIterate) {
				if (debug) {
					logger.debug("Processing injected element of bean '" + beanName + "': " + element);
				}
                //完成单个属性的注入
				element.inject(target, beanName, pvs);
			}
		}
	}

这里就是遍历了需要自动装配的属性,然后调用的是AutowiredFieldElement的inject方法完成每个属性的初始化,如下:

		@Override
		protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
			Field field = (Field) this.member;
			Object value;
			if (this.cached) {
				value = resolvedCachedArgument(beanName, this.cachedFieldValue);
			}
			else {
				DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
				desc.setContainingClass(bean.getClass());
				Set<String> autowiredBeanNames = new LinkedHashSet<String>(1);
				TypeConverter typeConverter = beanFactory.getTypeConverter();
				try {
                    //获取到属性对应的对象,这之前创建bean时,已经完成了创建
					value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
				}
				catch (BeansException ex) {
					throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
				}
				synchronized (this) {
					if (!this.cached) {
						if (value != null || this.required) {
							this.cachedFieldValue = desc;
							registerDependentBeans(beanName, autowiredBeanNames);
							if (autowiredBeanNames.size() == 1) {
								String autowiredBeanName = autowiredBeanNames.iterator().next();
								if (beanFactory.containsBean(autowiredBeanName)) {
									if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
										this.cachedFieldValue = new ShortcutDependencyDescriptor(
												desc, autowiredBeanName, field.getType());
									}
								}
							}
						}
						else {
							this.cachedFieldValue = null;
						}
						this.cached = true;
					}
				}
			}
			if (value != null) {
				ReflectionUtils.makeAccessible(field);
                //通过反射给属性赋值
				field.set(bean, value);
			}
		}
	}

先是调用beanFactory.resolveDependency方法,从Bean工厂中获取到属性对应的Bean对象,如StudentServiceImpl中的studentDao对象,最后调用field.set来为StudentServiceImpl中的studentDao属性赋值,这样就完成了StudentServiceImpl中的studentDao对象的自动装配

4.4 如果确保被自动装配的对象在装配时已经完成初始化?

我们刚才为StudentServiceImpl中的studentDao对象完成自动装配时,StudentDaoImpl已经完成了初始化,是因为IOC在初始化组件时,是扫描指定目录后,根据类名全路径依次初始化的,这样StudentDaoImpl正好在StudentServiceImpl前面完成初始化,如果我们把StudentDaoImpl的类名改下,改成StudentZDaoImpl,代码如下:

@Repository
public class StudentZDaoImpl implements StudentDao {

流程是怎么样的呢?我们回到AutowiredFieldElement类中的inject方法中,

@Override
		protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
			Field field = (Field) this.member;
			Object value;
			if (this.cached) {
				value = resolvedCachedArgument(beanName, this.cachedFieldValue);
			}
			else {
				DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
				desc.setContainingClass(bean.getClass());
				Set<String> autowiredBeanNames = new LinkedHashSet<String>(1);
				TypeConverter typeConverter = beanFactory.getTypeConverter();
				try {
                    //获得属性对应的对象
					value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
				}
				catch (BeansException ex) {
					throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
				}
                //省略部分代码
			}
			if (value != null) {
				ReflectionUtils.makeAccessible(field);
				field.set(bean, value);
			}
		}
	}

主要是通过DefaultListableBeanFactory的resolveDependency来获得属性的对象,我们来看看这个方法

	@Override
	public Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName,
			Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {

		descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
		if (xxx)
            //省略部分代码
		}
		else {
			Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
					descriptor, requestingBeanName);
			if (result == null) {
                //得到依赖的对象
				result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
			}
			return result;
		}
	}

主要是调用了doResolveDependency方法

	public Object doResolveDependency(DependencyDescriptor descriptor, String beanName,
			Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {

		    //主要看最后这里
			return (instanceCandidate instanceof Class ?
					descriptor.resolveCandidate(autowiredBeanName, type, this) : instanceCandidate);
		}
		finally {
			ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
		}
	}

调用了DependencyDescriptor的resolveCandidate方法

	public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
			throws BeansException {

		return beanFactory.getBean(beanName, requiredType);
	}

这里就回到了熟悉的配方了,通过beanName从Bean工厂中获取Bean,如果存在则直接返回已存在的Bean;如果不存在,则走创建的流程。

这里的StudentZDaoImpl此时就不存在,会先去创建,然后自动装配到StudentServiceImpl中的studentDao上。

4.5 如果解决循环依赖问题

上面讲到如果一个类依赖另外一个类,如果发现依赖的类还没创建,会去创建,但是如果要创建的类又依赖于当前的类会怎么样呢?会造成循环依赖的问题么?

比如我们定义一个A,交给容器管理,但是依赖了B

@Component
public class A {

    @Autowired
    private B b;

}

B的定义如下,B同样也依赖了A

@Service
public class B {

    @Autowired
    private A a;

}

Spring是怎么解决这个问题的呢?其实上面的分析流程已经能看出大概了

我们先看创建对象的过程主要是AbstractAutowireCapableBeanFactory中的doCreateBean方法

	protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {

		// 1. 初始化bean
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		
        //2. 缓存半成品bean及bean工厂,以便解决循环依赖的问题
		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		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));
		}

        //3. 初始化bean的实例(为属性赋值)
		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			populateBean(beanName, mbd, instanceWrapper);
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		catch (Throwable ex) {
			
		}


		return exposedObject;
	}

上面的流程主要分为3步:

  1. 实例化bean
  2. 把bean工厂缓存起来
  3. 初始化bean(为属性赋值)

我们看看addSingletonFactory方法

	protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(singletonFactory, "Singleton factory must not be null");
		synchronized (this.singletonObjects) {
			if (!this.singletonObjects.containsKey(beanName)) {
                //把bean工厂放到缓存中
				this.singletonFactories.put(beanName, singletonFactory);
				this.earlySingletonObjects.remove(beanName);
				this.registeredSingletons.add(beanName);
			}
		}
	}

然后我们看下初始化B时,要给其属性a赋值的流程,主要是DefaultSingletonBeanRegistry中的getSingleton方法

	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		//从成品bean的缓存中获取对象
        Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
                //从提前曝光未成品的bean中获取对象
				singletonObject = this.earlySingletonObjects.get(beanName);
				if (singletonObject == null && allowEarlyReference) {
                    //获取到相应的bean工厂
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
                        //提前曝光bean实例,主要用于解决AOP循环依赖
						singletonObject = singletonFactory.getObject();
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}

这里涉及到三级缓存:

  1. singletonObjects:成品bean
  2. earlySingletonObjects:提前暴露的bean(半成品bean)
  3. singletonFactory:bean工厂,用于提前暴露bean实例

整个流程就是先创建了A类的对象a,把bean工厂放入到缓存中;然后为A的属性b赋值,发现b不存在则创建B对象,创建完以后给B中的a赋值,从缓存中得到了A的bean工厂并得到半成品的a,完成了B的实例化,然后完成A中b的赋值,进而完成了A的实例化。于是AOP的循环依赖的问题得到了解决。

流程图如下:


版权声明:本文为luofen521原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。