前言
如果这是你第二次看到师长,说明你在觊觎我的美色!
点赞+关注再看,养成习惯
没别的意思,就是需要你的窥屏^_^
![ef1d6978b2f1cbc69c5456a698e64cd3.png](https://i-blog.csdnimg.cn/blog_migrate/f65beaa436ee90e89aa21c3ec35af722.jpeg)
本系列为SpringBoot深度源码专车系列,第一篇发车!
![ff253caca4830c1af7a9e78c901bb741.png](https://i-blog.csdnimg.cn/blog_migrate/de486439038bf0343a56438403be97e6.jpeg)
专车介绍
该趟专车是开往Spring Boot自动注入原理源码分析的专车
专车问题
- Spring Boot何时注入@Autowired标注的属性?
- 如果注入类型的Bean存在多个Spring Boot是如何处理的?
专车示例
- 定义接口
public interface PersonService { String hello(String name);}
- 定义接口的一个实现
@Service(value = "studentService")public class StudentServiceImpl implements PersonService { @Override public String hello(String name) { return "[student service] hello " + name; }}
- 定义接口的另一个实现
@Service(value = "teacherService")public class TeacherServiceImpl implements PersonService { @Override public String hello(String name) { return "[teacher service] hello " + name; }}
- 定义控制器
@RestControllerpublic class TestController {@Autowiredprivate PersonService studentService;@Autowiredprivate PersonService teacherService;@GetMapping("/hello")public String hello(@RequestParam(name = "name") String name) {return studentService.hello(name) + "=======>" + teacherService.hello(name);}}
以上示例代码很简单,创建了一个接口,接口有两个实现类,然后在控制器中注入实现类,从而完成业务方法的调用。接下来我们就开始对源码进行分析
专车分析
在分析代码之前我们先回忆一下操作对象的步骤:
- 首先我们会实例化一个对象
- 然后调用对象的set方法来设置对象的属性
有了上面的基础知识,接下来就开始揭秘旅程
寻找入口
在分析源码的时候最关键的一步就是寻找程序的入口,有了入口我们就成功了一半,那么如何寻找程序的入口?针对此处的源码分析,我们可以在TestController类上打一个断点,然后查看调用链
![f1c8318015ff62932b3574c366132519.png](https://i-blog.csdnimg.cn/blog_migrate/da10a2213bdc04b6cb0b8a11efd8afae.jpeg)
基于调用链路,我们看到有一个doCreateBean方法,该方法就是用来创建bean的,也就是我们上面提到的实例化对象部分
实例化Bean
AbstractAutowireCapableBeanFactory#doCreateBean
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)throws BeanCreationException {// Instantiate the bean.BeanWrapper instanceWrapper = null;if (mbd.isSingleton()) {instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);}if (instanceWrapper == null) {// 创建beaninstanceWrapper = createBeanInstance(beanName, mbd, args);}final Object bean = instanceWrapper.getWrappedInstance();Class> beanType = instanceWrapper.getWrappedClass();// ...省略部分代码// Initialize the bean instance.Object exposedObject = bean;try {// 填充bean,也就是我们上面提到的调用对象的set方法设置对象属性populateBean(beanName, mbd, instanceWrapper);exposedObject = initializeBean(beanName, exposedObject, mbd);}// ...省略部分代码return exposedObject;}
填充bean
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {// ...省略代码PropertyDescriptor[] filteredPds = null;if (hasInstAwareBpps) {if (pvs == null) {pvs = mbd.getPropertyValues();}// 遍历所有的后置处理器for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;// 通过断点分析我们可以得知此处调用的是AutowiredAnnotationBeanPostProcessor#postProcessPropertiesPropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);if (pvsToUse == null) {if (filteredPds == null) {filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);}pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);if (pvsToUse == null) {return;}}pvs = pvsToUse;}}}if (needsDepCheck) {if (filteredPds == null) {filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);}checkDependencies(beanName, mbd, filteredPds, pvs);}if (pvs != null) {applyPropertyValues(beanName, mbd, bw, pvs);}}
处理属性
AutowiredAnnotationBeanPostProcessor#postProcessProperties
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {// 查找当前bean需要注入的元数据信息,以TestController为例,那么需要注入的就是studentService和teacherService两个属性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;}
注入属性 AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {// 获取属性,此处的属性就是studentServiceField field = (Field) this.member;// 属性对应的valueObject value;if (this.cached) {value = resolvedCachedArgument(beanName, this.cachedFieldValue);}else {DependencyDescriptor desc = new DependencyDescriptor(field, this.required);desc.setContainingClass(bean.getClass());Set autowiredBeanNames = new LinkedHashSet<>(1);Assert.state(beanFactory != null, "No BeanFactory available");TypeConverter typeConverter = beanFactory.getTypeConverter();try {// 解析属性依赖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) &&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);}}
解析属性依赖 DefaultListableBeanFactory#resolveDependency
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,@Nullable Set autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());if (Optional.class == descriptor.getDependencyType()) {return createOptionalDependency(descriptor, requestingBeanName);}else if (ObjectFactory.class == descriptor.getDependencyType() ||ObjectProvider.class == descriptor.getDependencyType()) {return new DependencyObjectProvider(descriptor, requestingBeanName);}else if (javaxInjectProviderClass == descriptor.getDependencyType()) {return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);}else {Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, requestingBeanName);if (result == null) {// 解析依赖result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);}return result;}}
解析属性依赖 DefaultListableBeanFactory#doResolveDependency
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,@Nullable Set autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);try {// ...省略代码// 解析多个Bean,比如Array、List、Map类型,有兴趣可以自己查看分析Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);if (multipleBeans != null) {return multipleBeans;}// 根据类型获取候选对象,针对studentService而言,该属性的类型为PersonService// PersonService有2个实现类,StudentServiceImpl和TeacherServiceImpl// 所以此处获取结果为StudentServiceImpl对象和TeacherServiceImpl对象Map matchingBeans = findAutowireCandidates(beanName, type, descriptor);if (matchingBeans.isEmpty()) {if (isRequired(descriptor)) {raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);}return null;}String autowiredBeanName;Object instanceCandidate;// 重点处理,如果存在多个匹配的beanif (matchingBeans.size() > 1) {// 从已经匹配的bean中选择一个符合的beanautowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);if (autowiredBeanName == null) {// 如果bean必须注入或者存在多个匹配的bean,则抛出异常if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);}else {// In case of an optional Collection/Map, silently ignore a non-unique case:// possibly it was meant to be an empty collection of multiple regular beans// (before 4.3 in particular when we didn't even look for collection beans).return null;}}// 根据bean名称获取对应的示例instanceCandidate = matchingBeans.get(autowiredBeanName);}else {// We have exactly one match.Map.Entry entry = matchingBeans.entrySet().iterator().next();autowiredBeanName = entry.getKey();instanceCandidate = entry.getValue();}if (autowiredBeanNames != null) {autowiredBeanNames.add(autowiredBeanName);}if (instanceCandidate instanceof Class) {instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);}Object result = instanceCandidate;if (result instanceof NullBean) {if (isRequired(descriptor)) {raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);}result = null;}if (!ClassUtils.isAssignableValue(type, result)) {throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());}// 返回对应的示例对象return result;}finally {ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);}}
此处主要根据类型获取所有匹配的bean,如果匹配的bean有多个,那么最后会选择一个符合条件的bean名称,然后将对应的bena实例返回,调用set方法进行进行注入,到此注入的原理本该结束了。但是还是要分析一下Spring Boot是如何选择出符合条件的bean?
选择符合条件的bean DefaultListableBeanFactory#determineAutowireCandidate
protected String determineAutowireCandidate(Map candidates, DependencyDescriptor descriptor) {Class> requiredType = descriptor.getDependencyType();// 如果bean对应的primary属性为true,则返回bean对应的名称String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);if (primaryCandidate != null) {return primaryCandidate;}// 如果候选bean使用javax.annotation.Priority标注,返回高优先级bean对应的名称String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);if (priorityCandidate != null) {return priorityCandidate;}// Fallback// 如果匹配bean的名称和需要注入的属性名称一致,则返回匹配bean的名称for (Map.Entry entry : candidates.entrySet()) {String candidateName = entry.getKey();Object beanInstance = entry.getValue();if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||matchesBeanName(candidateName, descriptor.getDependencyName())) {return candidateName;}}return null;}
获取符合条件bean名称总结:
- 依据Bean的primary属性
- 依据javax.annotation.Priority
- 依据注入属性的名称
专车总结
- Bean实例化完成后,填充Bean
- 调用AutowiredAnnotationBeanPostProcessor#postProcessProperties处理属性
- 获取所有需要注入的属性
- 根据注入属性的类型从IOC容器中查找匹配实例
- 如果匹配实例存在多个,根据primary属性--->javax.annotation.Priority注解--->注入属性名称依次过滤,返回符合条件的Bean名称
- 过滤之后,存在一个符合条件的Bean名称,则返回对应的实例,否则抛出异常
专车回顾
回顾一下开头的2个问题:
- Spring Boot何时注入@Autowired标注的属性?
- 如果注入类型的Bean存在多个Spring Boot是如何处理的?
第一个问题:是在Bean实例化后,填充Bean的时候注入@Autowired标注的属性
第二个问题:如果存在多个类型的Bean,会根据primary--->javax.annotation.Priority--->名称依次过滤,得到最终匹配的bean名称
最后
师长,【java进阶架构师】号主,短短一年在各大平台斩获15W+程序员关注,专注分享Java进阶、架构技术、高并发、微服务、BAT面试、redis专题、JVM调优、Springboot源码、mysql优化等20大进阶架构专题。