基于AnnotationConfigApplicationContext的Bean加载过程(Spring Version 5.2.0)
建立个实体类
import lombok.Getter; import lombok.Setter; import lombok.ToString; @Getter @Setter @ToString public class Book { private String name; public Book(String name) { this.name = name; } }
再建立个配置类
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class BookConfig { @Bean public Book book(){ return new Book("BBB"); } }
最后是启动程序
import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class Main { public static void main(String[] args) throws Exception { ApplicationContext context = new AnnotationConfigApplicationContext(BookConfig.class); Book book = context.getBean(Book.class); System.out.println(book); } }
主要看getBean的过程
1. 首先进入org.springframework.context.support.AbstractApplicationContext#getBean(java.lang.Class<T>)
2. 进入org.springframework.context.support.GenericApplicationContext#getBeanFactory
3. 进入org.springframework.beans.factory.support.DefaultListableBeanFactory#getBean(java.lang.Class<T>)
实际上调用的是重载方法getBean,在其中调用的是resolveBean方法,解析bean。
==========================================对比==========================================
等一等??看网上其它教程都会有个doGetBean的东西,到这里怎么没有了?
我们知道目前常见的创建Application的方式有三种
FileSystemXmlApplicationContext/ClassPathXmlApplicationContext/AnnotationConfigApplicationContext
你以为我想说和上下文类型有关系?但是我告诉你和应用上下文的类型是没有任何关系的!这三种主要的区别就是读取配置的来源不同罢了,内部调用的都是refresh方法。
真正导致调用的方法不同,取决于你调用的是AbstractApplicationContext#getBean的哪一个重载方法。
第一个参数为String类型的getBean方法,最终会调用的AbstractBeanFactory#doGetBean
第一个参数为Class类型的getBean方法,最终会调用的DefaultListableBeanFactory#resolveBean
另外,后者resolveBean会调用doGetBean方法。
如红框的会跑到AbstractBeanFactory类里
蓝框的跑到DefaultListableBeanFactory类里
4. 根据传入的Class,先封装成ResolvableType。(对于指定的Class,返回一个ResolvableType,仅对原始类执行可分配性检查,这是一个包装器。)
5. 带着ResolveableType进入org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveBean
@Nullable private <T> T resolveBean(ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) { // 根据传入的ResolvableType,返回一个NamedBeanHolder(一个持有bean名称和bean实例的容器) NamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, args, nonUniqueAsNull); // 如果namedBean不为空,则直接返回实例 if (namedBean != null) { return namedBean.getBeanInstance(); } // namedBean为空(比如我获取了一个不存在的bean)则执行以下内容↓ // 获取父bean工厂 BeanFactory parent = getParentBeanFactory(); // 如果是DefaultListableBeanFactory的实例,则正常解析 if (parent instanceof DefaultListableBeanFactory) { return ((DefaultListableBeanFactory) parent).resolveBean(requiredType, args, nonUniqueAsNull); } // 不是DefaultListableBeanFactory的实例并且不为空(这一步具体干啥还不清楚) else if (parent != null) { ObjectProvider<T> parentProvider = parent.getBeanProvider(requiredType); if (args != null) { return parentProvider.getObject(args); } else { return (nonUniqueAsNull ? parentProvider.getIfUnique() : parentProvider.getIfAvailable()); } } // parent也为空,则返回空 return null; }
这个方法呢,主要调用了resolveNamedBean方法,利用返回持有名称和实例的容器获得bean实例。不是核心方法。
6. org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveNamedBean(org.springframework.core.ResolvableType, java.lang.Object[], boolean)
这个方法干的事情就比较多了
@SuppressWarnings("unchecked") @Nullable private <T> NamedBeanHolder<T> resolveNamedBean( ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) throws BeansException { Assert.notNull(requiredType, "Required type must not be null"); // 根据类型获取bean名称---① String[] candidateNames = getBeanNamesForType(requiredType); // 如果bean名称不止一个(比如你定义了多个同类型但是名称不一样的Bean) if (candidateNames.length > 1) { // 自动装配候选者列表 List<String> autowireCandidates = new ArrayList<>(candidateNames.length); // 遍历bean名称 for (String beanName : candidateNames) { // 判断:如果beanDefinitionMap不包含key为beanName的键值对或者该bean可以被自动装配到其他bean中。则添加到候选列表中 if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) { autowireCandidates.add(beanName); } } // 候选列表不为空,则给候选名称重新赋值 if (!autowireCandidates.isEmpty()) { candidateNames = StringUtils.toStringArray(autowireCandidates); } } // bean名称只有一个 if (candidateNames.length == 1) { // 因为只有一个,所以是0下标的名称 String beanName = candidateNames[0]; // 返回一个持有bean名称和bean实例的容器【getBean方法:绕了一圈,依然回到了AbstractBeanFactory#getBean,准确来说是doGetBean方法】---② return new NamedBeanHolder<>(beanName, (T) getBean(beanName, requiredType.toClass(), args)); } else if (candidateNames.length > 1) { Map<String, Object> candidates = new LinkedHashMap<>(candidateNames.length); // 遍历候选名称 for (String beanName : candidateNames) { // 如果是单例并且args为空 if (containsSingleton(beanName) && args == null) { // getBean实例化bean【getBean方法:绕了一圈,依然回到了AbstractBeanFactory#getBean,准确来说是doGetBean方法】 Object beanInstance = getBean(beanName); // 放进候选Map里,value是bean实例 candidates.put(beanName, (beanInstance instanceof NullBean ? null : beanInstance)); } else { // 否则直接范进Map里,value是bean的Class candidates.put(beanName, getType(beanName)); } } // 因为这个方法只能返回一个实例,而这种情况我们获取了多个,到底返回哪一个? // 这一步:确定给定bean集合中的主要候选对象。---③ String candidateName = determinePrimaryCandidate(candidates, requiredType.toClass()); if (candidateName == null) { // 这一步:确定给定bean集合中具有最高优先级的对象。---④ candidateName = determineHighestPriorityCandidate(candidates, requiredType.toClass()); } // 如果确定了返回哪一个对象 if (candidateName != null) { // 从候选集合中选出目标对象 Object beanInstance = candidates.get(candidateName); // 没有实例化则实例化 if (beanInstance == null || beanInstance instanceof Class) { beanInstance = getBean(candidateName, requiredType.toClass(), args); } // 返回包装类 return new NamedBeanHolder<>(candidateName, (T) beanInstance); } // 前面都没确定出来,那只能抛异常了。 if (!nonUniqueAsNull) { // 比如:No qualifying bean of type 'com.demo.tools.Book' available: expected single matching bean but found 2 throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet()); } } return null; }
总结:
1. 根据传入的类型获取bean的所有名称。
2. 过滤候选bean名称。
3. 如果bean名称只有一个,那么直接调用AbstractBeanFactory里的doGetBean进行实例化并返回。
3. 如果bean名称有多个,则选出主要候选名称或者最高优先级的名称来帮助实例化。如果没有选出可用的名称,则抛出bean定义冲突异常。
下面看一下其它方法:
①:根据类型获取名称列表
@Override public String[] getBeanNamesForType(ResolvableType type) { return getBeanNamesForType(type, true, true); } @Override public String[] getBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) { Class<?> resolved = type.resolve(); // 如果resolved不为空,并且不是泛型参数 if (resolved != null && !type.hasGenerics()) { // 虽然调用了这个方法,但是这个方法实际上调用的也是doGetBeanNamesForType return getBeanNamesForType(resolved, includeNonSingletons, includeNonSingletons); } else { return doGetBeanNamesForType(type, includeNonSingletons, includeNonSingletons); } } @Override public String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) { // 正常来讲不会走这里,这里是什么情况?? if (!isConfigurationFrozen() || type == null || !allowEagerInit) { return doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit); } // 先从缓存中找 Map<Class<?>, String[]> cache = (includeNonSingletons ? this.allBeanNamesByType : this.singletonBeanNamesByType); String[] resolvedBeanNames = cache.get(type); if (resolvedBeanNames != null) { return resolvedBeanNames; } // 缓存没有,则创建,并放到缓存中 resolvedBeanNames = doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, true); if (ClassUtils.isCacheSafe(type, getBeanClassLoader())) { cache.put(type, resolvedBeanNames); } return resolvedBeanNames; } // NamedBeanHolder:持有beanName和beanInstance的包装类 // BeanDefinitionHolder:包含名称和别名以及bean定义的Holder。可以注册为内部bean的占位符。 // 重点类:RootBeanDefinition、DefaultSingletonBeanRegistry private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) { List<String> result = new ArrayList<>(); // 检查全部的bean定义 for (String beanName : this.beanDefinitionNames) { // 只有当bean名称没有定义为其他bean的别名时,才认为bean是合格的 if (!isAlias(beanName)) { try { // 返回合并的RootBeanDefinition,如果指定的bean符合子bean定义,则遍历父bean定义。【为什么要合并定义?后面会讲】 RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); // 只有在bean定义完成时才检查它。 if (!mbd.isAbstract() && (allowEagerInit || (mbd.hasBeanClass() || !mbd.isLazyInit() || isAllowEagerClassLoading()) && !requiresEagerInitForType(mbd.getFactoryBeanName()))) { // 检查给定的bean是否定义为FactoryBean。 boolean isFactoryBean = isFactoryBean(beanName, mbd); // 返回由这个bean定义修饰的目标定义 BeanDefinitionHolder dbd = mbd.getDecoratedDefinition(); boolean matchFound = false; // 允许FactoryBean初始化(allowEagerInit==true 或者 这个bean是单例bean) boolean allowFactoryBeanInit = allowEagerInit || containsSingleton(beanName); // boolean isNonLazyDecorated = dbd != null && !mbd.isLazyInit(); // 不是FactoryBean if (!isFactoryBean) { if (includeNonSingletons || isSingleton(beanName, mbd, dbd)) { // 检查给定名称的bean是否与指定的类型匹配。允许应用额外的约束,以确保不过早地创建bean。 // 注意这个isTypeMatch方法是@since 5.2新加的,内容过多,暂且不谈 matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit); } } // 是FactoryBean else { if (includeNonSingletons || isNonLazyDecorated || (allowFactoryBeanInit && isSingleton(beanName, mbd, dbd))) { matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit); } // 不匹配 if (!matchFound) { // In case of FactoryBean, try to match FactoryBean instance itself next. beanName = FACTORY_BEAN_PREFIX + beanName; matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit); } } // 只有匹配的才会记录下来 if (matchFound) { result.add(beanName); } } } catch (CannotLoadBeanClassException | BeanDefinitionStoreException ex) { if (allowEagerInit) { throw ex; } // Probably a placeholder: let's ignore it for type matching purposes. LogMessage message = (ex instanceof CannotLoadBeanClassException) ? LogMessage.format("Ignoring bean class loading failure for bean '%s'", beanName) : LogMessage.format("Ignoring unresolvable metadata in bean definition '%s'", beanName); logger.trace(message, ex); onSuppressedException(ex); } } } // 检查手动注册的单例。 for (String beanName : this.manualSingletonNames) { try { // 对于FactoryBean,匹配FactoryBean创建的对象。【org.springframework.beans.factory.FactoryBean】(FactoryBean后面也会讲) if (isFactoryBean(beanName)) { if ((includeNonSingletons || isSingleton(beanName)) && isTypeMatch(beanName, type)) { result.add(beanName); // 已经匹配过这个bean,跳过 continue; } // 对于FactoryBean,接下来尝试匹配FactoryBean本身。 beanName = FACTORY_BEAN_PREFIX + beanName; } // 匹配原始bean实例(可能是原始的FactoryBean)。 if (isTypeMatch(beanName, type)) { result.add(beanName); } } catch (NoSuchBeanDefinitionException ex) { // Shouldn't happen - probably a result of circular reference resolution... logger.trace(LogMessage.format("Failed to check manually registered singleton with name '%s'", beanName), ex); } } return StringUtils.toStringArray(result); }
这么多逻辑,无非作者考虑的很周全,实际上只是一个根据类型获取bean名称的过程。另外你还能发现Spring的命名特点,getXXX方法仅仅是做了一些准备工作,真正工作的是doGetXXX方法。
②:doGetBean方法
这个方法比较复杂,涉及到其它的方法也很多,所以我在后面单独一部分讲解,麻烦移步后面。
③:获取主要候选名称
protected String determinePrimaryCandidate(Map<String, Object> candidates, Class<?> requiredType) { String primaryBeanName = null; // 遍历候选名称集合 for (Map.Entry<String, Object> entry : candidates.entrySet()) { String candidateBeanName = entry.getKey(); Object beanInstance = entry.getValue(); // 如果是主要候选对象。这里返回bean定义里的primary对象的值,具体来说就是如果你定义bean的时候用@Primary注解标注的,则是true if (isPrimary(candidateBeanName, beanInstance)) { // 因为是循环所有的候选名称,第一次primaryBeanName肯定是null,所以在else语句给它赋值。如果出现了多个Primary注解的bean,那就会抛出异常 if (primaryBeanName != null) { boolean candidateLocal = containsBeanDefinition(candidateBeanName); boolean primaryLocal = containsBeanDefinition(primaryBeanName); if (candidateLocal && primaryLocal) { throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(), "more than one 'primary' bean found among candidates: " + candidates.keySet()); } else if (candidateLocal) { primaryBeanName = candidateBeanName; } } else { primaryBeanName = candidateBeanName; } } } return primaryBeanName; }
总结:如果出现了多个候选名称,则会选出被@Primary注解标注的bean。如果出现多个@Primary的bean,依然会抛出异常。
④:获取最高优先级名称
protected String determineHighestPriorityCandidate(Map<String, Object> candidates, Class<?> requiredType) { String highestPriorityBeanName = null; Integer highestPriority = null; for (Map.Entry<String, Object> entry : candidates.entrySet()) { String candidateBeanName = entry.getKey(); Object beanInstance = entry.getValue(); if (beanInstance != null) { // 获取优先级,通过Primary的例子,这个也可以猜出是标记了@Priority注解,数字越小优先级越高。 // @Priority注解需要单独引入依赖: // <dependency> // <groupId>javax.annotation</groupId> // <artifactId>javax.annotation-api</artifactId> // <version>1.3.2</version> // </dependency> Integer candidatePriority = getPriority(beanInstance); if (candidatePriority != null) { if (highestPriorityBeanName != null) { if (candidatePriority.equals(highestPriority)) { throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(), "Multiple beans found with the same priority ('" + highestPriority + "') among candidates: " + candidates.keySet()); } else if (candidatePriority < highestPriority) { highestPriorityBeanName = candidateBeanName; highestPriority = candidatePriority; } } else { highestPriorityBeanName = candidateBeanName; highestPriority = candidatePriority; } } } } return highestPriorityBeanName; }
主要方法调用流程
核心方法依然是org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
先看一下重点步骤,然后分步解释
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { // 1. 转换bean名称 final String beanName = transformedBeanName(name); Object bean; // 2. 检查单例缓存中手动注册的单例对象 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 + "'"); } } // 3. 获取给定bean实例的对象,可能是它本身,也可能是FactoryBean创建的对象。 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { // 如果指定的原型bean正在创建,则抛出异常 if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // 获取父工厂 BeanFactory parentBeanFactory = getParentBeanFactory(); // 当前工厂里不存在这个bean定义则在父工厂里面找 if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { // 获取原始bean名称 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); } // 下面就是创建的过程了 try { // 4. 合并bean定义,拿到RootBeanDefinition final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); // 检查bean定义 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 + "'"); } // 5. 给当前bean注册一个依赖bean registerDependentBean(dep, beanName); try { // 递归实例化依赖 getBean(dep); } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex); } } } // 6. 创建单实例bean 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; } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } // 7. 创建多实例bean 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); } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } else { // 8. 在指定的scope上实例化bean String scopeName = mbd.getScope(); final 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); } }); bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); } catch (IllegalStateException ex) { throw new BeanCreationException(beanName, "Scope '" + scopeName + "' is not active for the current thread; consider " + "defining a scoped proxy for this bean if you intend to refer to it from a singleton", ex); } } } catch (BeansException ex) { cleanupAfterBeanCreationFailure(beanName); throw ex; } } // 9. 检查所需的类型是否与实际bean实例的类型相匹配。 if (requiredType != null && !requiredType.isInstance(bean)) { try { T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType); if (convertedBean == null) { throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } return convertedBean; } catch (TypeMismatchException ex) { if (logger.isTraceEnabled()) { logger.trace("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'", ex); } throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } } return (T) bean; }
大概过程:
1. 转换bean名称。
2. 查看缓存中有没有,有则直接返回。
3. 缓存没有,先找到并确定bean定义。
4. 合并bean定义。
5. 检查循环依赖。
6. 根据配置,创建单实例bean还是多实例bean还是scope范围的bean。
7. 做最后的类型检查,无误后返回。
下面分步骤
1. 转换bean名称。
protected String transformedBeanName(String name) { // beanName转换分两部分,一个是去掉工厂的取消引用前缀;一个是将别名解析为规范名称。 return canonicalName(BeanFactoryUtils.transformedBeanName(name)); } // 返回实际的bean名称,去掉工厂的取消引用前缀(如果有,也去掉重复的工厂前缀) public static String transformedBeanName(String name) { Assert.notNull(name, "'name' must not be null"); if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) { return name; } return transformedBeanNameCache.computeIfAbsent(name, beanName -> { do { beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length()); } while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)); // 只要发现beanName以&开头,就会去除&,所以你就算写一百个&也不会有错误。 return beanName; }); } // 确定原始名称,将别名解析为规范名称。 public String canonicalName(String name) { String canonicalName = name; // Handle aliasing... String resolvedName; do { // 根据传入的名称,从别名Map里查询 resolvedName = this.aliasMap.get(canonicalName); if (resolvedName != null) { canonicalName = resolvedName; } } while (resolvedName != null); return canonicalName; }
这里涉及两个扩展内容,第一个就是FactoryBean,第二个就是别名。
BeanFactory和FactoryBean?
BeanFactory是顶级接口,是IDC容器实现的基础。
FactoryBean是为用户准备的,用来实例化一些复杂的Bean,给上层应用带来便利。
来看个例子,重新修改配置类的内容,加入了一个FactoryBean,以及定义了别名。
import org.springframework.beans.factory.FactoryBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class BookConfig { @Bean(name = {"第一个是原始名称", "book", "tom", "cat"}) public BookFactoryBean book(){ BookFactoryBean bookFactoryBean = new BookFactoryBean(); bookFactoryBean.setBeanInfo("它们隐藏了实例化一些复杂bean 的细节,给上层应用带来了便利"); return bookFactoryBean; } } class BookFactoryBean implements FactoryBean<Book>{ private String beanInfo; @Override public Book getObject() throws Exception { return new Book("AAA"); } @Override public Class<?> getObjectType() { return Book.class; } public String getBeanInfo() { return beanInfo; } public void setBeanInfo(String beanInfo) { this.beanInfo = beanInfo; } }
运行程序代码
import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class Main { public static void main(String[] args) throws Exception { ApplicationContext context = new AnnotationConfigApplicationContext(BookConfig.class); // Book book = context.getBean(Book.class); Object bean = context.getBean("&&&book"); Object bean1 = context.getBean("第一个是原始名称"); Object bean2 = context.getBean("cat"); System.out.println(bean); System.out.println(bean1); System.out.println(bean2); } }
输出结果:
第一个问题:beanName前面加个&,代表获取FactoryBean。
第二个问题:无论用什么名称,在内部都会找到它的原始名称。
根据debug的结果可以看出:定位bean还是需要原始名称,如果传入的是原始名称,则直接返回。
总结:
转换beanName包含两部分:一个是去掉工厂的&前缀,另一个是利用AliasMap找到Bean的原始名称。
2. 检查单例缓存
这个方法在另一个类里:DefaultSingletonBeanRegistry#getSingleton(java.lang.String)
public Object getSingleton(String beanName) { // allowEarlyReference 为true return getSingleton(beanName, true); } // 根据名称找到注册的(原始)单例对象。 // 检查已经实例化的单例并允许对当前单例的早期引用(解析循环引用)。 protected Object getSingleton(String beanName, boolean allowEarlyReference) { // 这里获得的可能是bean也可能是FactoryBean Object singletonObject = this.singletonObjects.get(beanName); // 如果没有获取到并且发现当前bean正在创建 if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { synchronized (this.singletonObjects) { // 从早期单例对象缓存中尝试获取,有的话返回 singletonObject = this.earlySingletonObjects.get(beanName); // 如果从早期单例对象缓存中没有获取的,并且允许早期依赖 if (singletonObject == null && allowEarlyReference) { // 则获取单例工厂 ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { // 用工厂方法创建实例 singletonObject = singletonFactory.getObject(); // 放进早期单例对象缓存中 this.earlySingletonObjects.put(beanName, singletonObject); // 移除工厂缓存中的bean this.singletonFactories.remove(beanName); } } } } // 只要获取到,即返回 return singletonObject; }
这其中涉及了三个缓存
/** 单例对象缓存: beanName -> beanInstance. 存放创建完成的bean */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);/** 单例工厂缓存: beanName -> ObjectFactory. */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);/** 早期单例对象缓存: beanName -> beanInstance. 已经实例化但是还没有创建完成的单例bean被放到这里面,其目的是用来检测循环引用 */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);/** 已经注册的bean放在这里. */
private final Set<String> registeredSingletons = new LinkedHashSet<>(256);
获取过程很简单:先去缓存中寻找,缓存中没有去早期缓存中找,早期缓存没有则获取单例工厂,利用工厂方法获取实例,并添加到早期缓存中,同时移除工厂缓存中的bean。最后返回。对于Spring解决循环依赖的问题:
Spring只能解决单例模式下的Setter循环依赖,Spring不能解决prototype作用域的bean之间的循环依赖。
Spring在获取ClassA的实例时,不等ClassA完成创建就将其曝光加入正在创建的bean缓存中。
在解析ClassA的属性时,又发现依赖于ClassB,再次去获取ClassB,当解析ClassB的属性时,又发现需要ClassA的属性,
但此时的ClassA已经被提前曝光加入了正在创建的bean的缓存中,则无需创建新的的ClassA的实例,直接从缓存中获取即可。从而解决循环依赖问题。另外:根据代码逻辑不难发现,ClassA实例化的时候发现需要依赖ClassB,于是把ClassA先缓存起来,去实例化ClassB。也就是说,优先初始化最底层对象。
根据Debug的结果,这一步可能获取到的是个FactoryBean:
3. 获取真正实例对象getObjectForBeanInstance
因为上一步的过程,我们可以知道,返回结果不一定是我们需要的对象。
/** * org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#getObjectForBeanInstance * * @since 5.0 * @see #obtainFromSupplier */ @Override protected Object getObjectForBeanInstance( Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) { // 获取当前ThreadLocal存储的变量,也就是当前正在创建的bean String currentlyCreatedBean = this.currentlyCreatedBean.get(); if (currentlyCreatedBean != null) { // 如果当前有正在创建的bean,则注册为beanName所依赖的bean registerDependentBean(beanName, currentlyCreatedBean); } return super.getObjectForBeanInstance(beanInstance, name, beanName, mbd); } protected Object getObjectForBeanInstance( Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) { // 根据name判断我们需要的是不是FactoryBean(判断名字里有没有&) if (BeanFactoryUtils.isFactoryDereference(name)) { if (beanInstance instanceof NullBean) { return beanInstance; } if (!(beanInstance instanceof FactoryBean)) { throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass()); } if (mbd != null) { mbd.isFactoryBean = true; } // 返回FactoryBean实例 return beanInstance; } // 走到这里,证明我们需要的是bean实例,而不是FactoryBean实例。而到这里beanInstance可能是个bean,也可能是个FactoryBean。 // 如果它是一个FactoryBean,我们将使用它来创建一个bean实例 if (!(beanInstance instanceof FactoryBean)) { // 不是FactoryBean,直接返回即可。 return beanInstance; } Object object = null; if (mbd != null) { mbd.isFactoryBean = true; } else { // 根据beanName,从FactoryBean缓存中获取FactoryBean object = getCachedObjectForFactoryBean(beanName); } // FactoryBean缓存中没找到目标 if (object == null) { // 把当前的beanInstance强制转换成FactoryBean FactoryBean<?> factory = (FactoryBean<?>) beanInstance; // RootBeanDefinition为空并且beanDefinitionMap中包含次beanName if (mbd == null && containsBeanDefinition(beanName)) { // 合并bean定义,返回一个RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); } // 代表RootBeanDefinition是否是合成得到的 boolean synthetic = (mbd != null && mbd.isSynthetic()); // 从FactoryBean中获取bean实例 object = getObjectFromFactoryBean(factory, beanName, !synthetic); } return object; }
这部分的主要逻辑是:
1. 根据name判断我们需要的是个Bean实例还是FactoryBean实例。
2. 如果需要FactoryBean实例,则做一些校验后返回上一步得到的对象。
2. 如果需要Bean实例,则判断上一步返回的对象是不是个纯粹的Bean,是则返回;如果是个FactoryBean实例,则用FactoryBean创建一个Bean实例返回。
这部分涉及一个从FactoryBean中获取bean实例的过程:
// org.springframework.beans.factory.support.FactoryBeanRegistrySupport#getObjectFromFactoryBean protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) { // 是单例并且单例缓存中有此beanName的key if (factory.isSingleton() && containsSingleton(beanName)) { synchronized (getSingletonMutex()) { // 先检查缓存,这个factoryBeanObjectCache存储的是由FactoryBean创建的单例对象的缓存。key为FactoryBean名称。 Object object = this.factoryBeanObjectCache.get(beanName); if (object == null) { // factoryBeanObjectCache缓存没有,则执行FactoryBean的getObject方法,获取bean实例 object = doGetObjectFromFactoryBean(factory, beanName); // 考虑循环依赖的情况 Object alreadyThere = this.factoryBeanObjectCache.get(beanName); if (alreadyThere != null) { object = alreadyThere; } else { // 后置处理 if (shouldPostProcess) { if (isSingletonCurrentlyInCreation(beanName)) { // Temporarily return non-post-processed object, not storing it yet.. return object; } // 单例创建之前,将单例对象注册为当前正在创建的状态(添加到singletonsCurrentlyInCreation里) beforeSingletonCreation(beanName); try { // 在初始化之后应用后置处理 object = postProcessObjectFromFactoryBean(object, beanName); } catch (Throwable ex) { throw new BeanCreationException(beanName, "Post-processing of FactoryBean's singleton object failed", ex); } finally { // 最后将单例对象正在创建的状态移除(从singletonsCurrentlyInCreation里移除) afterSingletonCreation(beanName); } } // 因为是FactoryBean创建的bean,所以添加到对应的缓存里 if (containsSingleton(beanName)) { this.factoryBeanObjectCache.put(beanName, object); } } } // // 返回结果 return object; } } // 不是单例或者缓存中没有此beanName else { // 调用factory的getObject方法获取实例bean Object object = doGetObjectFromFactoryBean(factory, beanName); // 执行后置处理 if (shouldPostProcess) { try { object = postProcessObjectFromFactoryBean(object, beanName); } catch (Throwable ex) { throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex); } } // 返回结果 return object; } }
简单来讲:
1. 先从factoryBeanObjectCache缓存中查看是否存在此FactoryBean创建的单例,有则返回,没有的话执行FactoryBean的getObject方法来获取;
2. 获取完进行后置处理,后置处理之前将次beanName添加到 singletonsCurrentlyInCreation 集合中以示正在创建中,后置处理之后将beanName从 singletonsCurrentlyInCreation 集合中移除,以清除正在创建状态。
4. 这部分涉及了一个合并BeanDefinition的过程。关于BeanDefinition的结构如下:
-
待续
5. 注册依赖Bean
/** 别人依赖我:key=我,value=依赖我的人 */ private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64); /** 我依赖别人:key=我,value=我依赖的人 */ private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64); // beanName依赖dep registerDependentBean(dep, beanName); // beanName-被依赖者;dependentBeanName-依赖者 public void registerDependentBean(String beanName, String dependentBeanName) { String canonicalName = canonicalName(beanName); // 别人依赖我:key=beanName,value=Set(dependentBeanName) synchronized (this.dependentBeanMap) { Set<String> dependentBeans = this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8)); if (!dependentBeans.add(dependentBeanName)) { return; } } // 我依赖别人:key=dependentBeanName,value=Set(beanName) synchronized (this.dependenciesForBeanMap) { Set<String> dependenciesForBean = this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8)); dependenciesForBean.add(canonicalName); } }
这个依赖关系有点绕,要仔细一点捋一下。
dependentBeanMap:dependent【依赖】Bean【我】Map,key是被依赖者,value是依赖者
dependenciesForBeanMap:dependencies【依赖项】For【给】Bean【我】Map,key是依赖者,value是被依赖者不知道我这样解释能不能明白这个关系?
6. 创建单实例bean
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { if (logger.isTraceEnabled()) { logger.trace("Creating instance of bean '" + beanName + "'"); } RootBeanDefinition mbdToUse = mbd; // 确保此时bean已经解析,并在动态解析的类不能存储在共享的合并bean定义中时,克隆bean定义。【根据Bean定义解析BeanClass】 Class<?> resolvedClass = resolveBeanClass(mbd, beanName); if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { mbdToUse = new RootBeanDefinition(mbd); mbdToUse.setBeanClass(resolvedClass); } try { // 验证&准备在该bean中定义的覆盖的方法。 // 检查是否存在具有指定名称的方法。 mbdToUse.prepareMethodOverrides(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", ex); } try { // 给 Bean后置处理器 一个机会,返回一个目标bean实例的代理 Object bean = resolveBeforeInstantiation(beanName, mbdToUse); // 代理不为空则返回 if (bean != null) { return bean; } } catch (Throwable ex) { throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", ex); } try { // 【执行创建bean的具体逻辑】 Object beanInstance = doCreateBean(beanName, mbdToUse, args); if (logger.isTraceEnabled()) { logger.trace("Finished creating instance of bean '" + beanName + "'"); } return beanInstance; } catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) { // A previously detected exception with proper bean creation context already, // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry. throw ex; } catch (Throwable ex) { throw new BeanCreationException( mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex); } }
这个方法主要有三步:
1. 解析BeanClass
2. 验证&准备Bean定义中覆盖的方法
3. 执行创建Bean
来看doCreateBean
// 【执行创建bean的具体逻辑】 protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { // BeanWrapper是个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.getWrappedInstance(); Class<?> beanType = instanceWrapper.getWrappedClass(); if (beanType != NullBean.class) { mbd.resolvedTargetType = beanType; } // Allow post-processors to modify the merged bean definition. 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; } } // 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)); } // Initialize the bean instance. Object exposedObject = bean; try { // ☆☆☆【属性赋值】 populateBean(beanName, mbd, instanceWrapper); // ☆☆☆【初始化Bean实例】 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); } } // 如果是提前暴露单例 if (earlySingletonExposure) { Object earlySingletonReference = getSingleton(beanName, false); if (earlySingletonReference != null) { if (exposedObject == bean) { exposedObject = earlySingletonReference; } else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { String[] dependentBeans = getDependentBeans(beanName); Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length); for (String dependentBean : dependentBeans) { if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { actualDependentBeans.add(dependentBean); } } if (!actualDependentBeans.isEmpty()) { throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been " + "wrapped. This means that said other beans do not use the final version of the " + "bean. This is often the result of over-eager type matching - consider using " + "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example."); } } } } // 将bean注册为一次性的 try { registerDisposableBeanIfNecessary(beanName, bean, mbd); } catch (BeanDefinitionValidationException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex); } return exposedObject; }
这部分同样也主要分为三步,同时这也是Bean生命周期的体现
1. ☆☆☆【实例化Bean】
2. ☆☆☆【属性赋值】
3. ☆☆☆【初始化Bean实例】
4. ☆☆☆【销毁】(销毁在这里没有体现)
☆☆☆【实例化Bean】☆☆☆
// 通过适当的策略实例化Bean:工厂方法、构造方法自动装配或者简单实例化 protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { // Make sure bean class is actually resolved at this point. Class<?> beanClass = resolveBeanClass(mbd, beanName); if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Bean class isn't public, and non-public access not allowed: " + beanClass.getName()); } // 获取创建bean实例的回调 Supplier<?> instanceSupplier = mbd.getInstanceSupplier(); if (instanceSupplier != null) { // 利用instanceSupplier获取一个Bean实例 return obtainFromSupplier(instanceSupplier, beanName); } // 如果工厂方法不为空 if (mbd.getFactoryMethodName() != null) { // 通过工厂方法实例化Bean(详见:org.springframework.beans.factory.support.ConstructorResolver#instantiateUsingFactoryMethod) return instantiateUsingFactoryMethod(beanName, mbd, args); } // Shortcut when re-creating the same bean... boolean resolved = false; boolean autowireNecessary = false; if (args == null) { synchronized (mbd.constructorArgumentLock) { if (mbd.resolvedConstructorOrFactoryMethod != null) { resolved = true; autowireNecessary = mbd.constructorArgumentsResolved; } } } // 如果已解析 if (resolved) { // 如果自动装配 if (autowireNecessary) { // 构造方法自动装配(详见:org.springframework.beans.factory.support.ConstructorResolver#autowireConstructor) return autowireConstructor(beanName, mbd, null, null); } // 否则是普通的实例化 else { return instantiateBean(beanName, mbd); } } // 返回用于给定bean的候选构造函数,检查所有已注册的构造函数 Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { // 构造方法自动装配(详见:org.springframework.beans.factory.support.ConstructorResolver#autowireConstructor) return autowireConstructor(beanName, mbd, ctors, args); } // 如果有默认的构造函数 ctors = mbd.getPreferredConstructors(); if (ctors != null) { return autowireConstructor(beanName, mbd, ctors, null); } // 没有特殊的处理器,使用无参构造函数 return instantiateBean(beanName, mbd); }
这个方法主要是选取适当的策略来决定如何创建Bean
1. 利用Bean定义中的instanceSupplier获取Bean
2. 利用指定的工厂方法名称实例化Bean
3. 利用构造方法自动装配实例化Bean
4. 简单的使用无参构造函数实例化Bean,这个也是默认的处理方式
选择默认处理方式:
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) { try { Object beanInstance; final BeanFactory parent = this; if (System.getSecurityManager() != null) { beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(mbd, beanName, parent), getAccessControlContext()); } else { // org.springframework.beans.factory.support.SimpleInstantiationStrategy#instantiate(org.springframework.beans.factory.support.RootBeanDefinition, java.lang.String, org.springframework.beans.factory.BeanFactory) beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent); } // 新建一个Bean包装类 BeanWrapper bw = new BeanWrapperImpl(beanInstance); // 初始化Bean包装类 initBeanWrapper(bw); return bw; } catch (Throwable ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex); } }
这个方法描述了两个主要步骤
1. 实例化Bean
2. 新建 & 初始化包装类,并返回。
看实例化
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) { // 如果没有覆盖的方法,则不使用CGLIB覆盖 if (!bd.hasMethodOverrides()) { Constructor<?> constructorToUse; synchronized (bd.constructorArgumentLock) { constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod; if (constructorToUse == null) { // 获取Class对象 final Class<?> clazz = bd.getBeanClass(); if (clazz.isInterface()) { throw new BeanInstantiationException(clazz, "Specified class is an interface"); } try { if (System.getSecurityManager() != null) { constructorToUse = AccessController.doPrivileged( (PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor); } else { // 获取Constructor对象 constructorToUse = clazz.getDeclaredConstructor(); } // 给RootBeanDefinition设置已解析的构造函数或工厂方法 bd.resolvedConstructorOrFactoryMethod = constructorToUse; } catch (Throwable ex) { throw new BeanInstantiationException(clazz, "No default constructor found", ex); } } } // 工具类,实例化Bean(绕了这么多,真正干活的是这个方法) return BeanUtils.instantiateClass(constructorToUse); } else { // Must generate CGLIB subclass. // 子类可以覆盖这个方法,如果子类可以用给定的RootBeanDefinition中指定的方法注入实例化一个对象。实现该方法的目的是抛出UnsupportedOperationException。 // 实例化应该使用无参数的构造函数。 return instantiateWithMethodInjection(bd, beanName, owner); } } public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException { Assert.notNull(ctor, "Constructor must not be null"); try { // 反射方法(ctor.setAccessible(true);) ReflectionUtils.makeAccessible(ctor); if (KotlinDetector.isKotlinReflectPresent() && KotlinDetector.isKotlinType(ctor.getDeclaringClass())) { return KotlinDelegate.instantiateClass(ctor, args); } else { // 获得参数类型 Class<?>[] parameterTypes = ctor.getParameterTypes(); // 参数数量校验 Assert.isTrue(args.length <= parameterTypes.length, "Can't specify more arguments than constructor parameters"); Object[] argsWithDefaultValues = new Object[args.length]; // 组装参数 for (int i = 0 ; i < args.length; i++) { if (args[i] == null) { Class<?> parameterType = parameterTypes[i]; argsWithDefaultValues[i] = (parameterType.isPrimitive() ? DEFAULT_TYPE_VALUES.get(parameterType) : null); } else { argsWithDefaultValues[i] = args[i]; } } // 反射方法,利用给定的参数new一个实例 return ctor.newInstance(argsWithDefaultValues); } } catch (InstantiationException ex) { throw new BeanInstantiationException(ctor, "Is it an abstract class?", ex); } catch (IllegalAccessException ex) { throw new BeanInstantiationException(ctor, "Is the constructor accessible?", ex); } catch (IllegalArgumentException ex) { throw new BeanInstantiationException(ctor, "Illegal arguments for constructor", ex); } catch (InvocationTargetException ex) { throw new BeanInstantiationException(ctor, "Constructor threw exception", ex.getTargetException()); } }
实际上实例化的方法并不复杂,复杂的是前期准备的过程
实例化的过程:组装参数成一个Object数组(无参的话数组长度为0),传入Constructor的newInstance方法完成实例化。
实例化全程总结:
1. 根据情况选取合适的创建策略
☆ 利用Bean定义中的instanceSupplier获取Bean
☆ 利用指定的工厂方法名称实例化Bean
☆ 利用构造方法自动装配实例化Bean
☆ 简单的使用无参构造函数实例化Bean,这个也是默认的处理方式
2. 将实例封装成一个包装类
☆ 通过反射方法实例化Bean
☆ 新建 & 初始化Bean的包装类
另外:我看了下利用工厂方法创建和构造方法自动装配两种方式,除了过程比较复杂,其实例化的时候调用的都是org.springframework.beans.factory.support.ConstructorResolver#instantiate(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
进而调用org.springframework.beans.factory.support.SimpleInstantiationStrategy#instantiate(org.springframework.beans.factory.support.RootBeanDefinition, java.lang.String, org.springframework.beans.factory.BeanFactory, java.lang.Object, java.lang.reflect.Method, java.lang.Object...)
刚好和上面对上,实例化都是利用反射(当然这样说也不是很严谨),因为实例化策略的实现有两个,除了反射还有CGLIB,如图:
☆☆☆【属性赋值】☆☆☆
// ☆☆☆【属性赋值】 protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { // Bean实例为空的不用属性赋值 if (bw == null) { if (mbd.hasPropertyValues()) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance"); } else { // Skip property population phase for null instance. return; } } // 给任何一个InstantiationAwareBeanPostProcessor在属性设置之前修改bean状态的机会。 boolean continueWithPropertyPopulation = true; // 如果Bean定义不是合成的,并且,当前的工厂持有InstantiationAwareBeanPostProcessor列表 if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { // 遍历用于此工厂创建bean的beanpostprocessor列表 for (BeanPostProcessor bp : getBeanPostProcessors()) { // 如果当前Processor是InstantiationAwareBeanPostProcessor的子类实现 if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; // 如果不是实例化之后的处理器,则设置continueWithPropertyPopulation为false,目的不再执行后续属性设置 if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { continueWithPropertyPopulation = false; break; } } } } // 注:InstantiationAwareBeanPostProcessor出现在Bean实例化前后,属性(自动装配)之前。 // 根据上面的执行结果,决定是否还要继续 if (!continueWithPropertyPopulation) { return; } // 尝试获取Bean定义里的属性值映射列表 PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); // 获取解析到的自动装配模式 int resolvedAutowireMode = mbd.getResolvedAutowireMode(); // 如果是根据名称自动装配或者根据类型自动装配,这里仅仅是将属性名称-属性值的映射关系装配到PropertyValues对象中 if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // Add property values based on autowire by name if applicable. if (resolvedAutowireMode == AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // Add property values based on autowire by type if applicable. if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } // 当前的工厂是否持有InstantiationAwareBeanPostProcessor列表 boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); // 是否需要检查依赖 boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); PropertyDescriptor[] filteredPds = null; // 如果当前的工厂持有InstantiationAwareBeanPostProcessor列表 if (hasInstAwareBpps) { if (pvs == null) { pvs = mbd.getPropertyValues(); } // 遍历执行处理器,对属性进行后置处理 for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; PropertyValues 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); } }
大概流程是
1. 进行Bean实例化之后的后置处理。
2. 先获取默认的属性映射关系对象,然后根据模式判断按照名称还是按照类型自动装配。
3. 遍历后置处理器,对装配好的属性映射关系对象进行后置处理。
4. 检查依赖。
5. 属性赋值。
另:autowireByName/autowireByType/applyPropertyValues这三个方法暂时不提,太多了。
☆☆☆【初始化Bean实例】☆☆☆
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)
// ☆☆☆【初始化Bean实例】 protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareMethods(beanName, bean); return null; }, getAccessControlContext()); } else { // 1. 执行Aware子类相关的方法 invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { // 2. 初始化之前的后置处理 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { // 3. 执行初始化方法 invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } if (mbd == null || !mbd.isSynthetic()) { // 4. 初始化之后的后置处理 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }
1. Aware的子类
private void invokeAwareMethods(final String beanName, final Object bean) { // Aware是个顶级标记接口,作用是能够感知自己的一些属性。示例在后面单独说明。 if (bean instanceof Aware) { if (bean instanceof BeanNameAware) { ((BeanNameAware) bean).setBeanName(beanName); } if (bean instanceof BeanClassLoaderAware) { ClassLoader bcl = getBeanClassLoader(); if (bcl != null) { ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl); } } if (bean instanceof BeanFactoryAware) { ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this); } } }
2、3 . 初始化前后的处理
@Override public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor processor : getBeanPostProcessors()) { // 遍历后置处理器,调用初始化之前的后置处理方法 Object current = processor.postProcessBeforeInitialization(result, beanName); if (current == null) { return result; } result = current; } return result; } @Override public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor processor : getBeanPostProcessors()) { // 遍历后置处理器,调用初始化之后的后置处理方法 Object current = processor.postProcessAfterInitialization(result, beanName); if (current == null) { return result; } result = current; } return result; }
4. 初始化方法
// 初始化 protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd) throws Throwable { boolean isInitializingBean = (bean instanceof InitializingBean); // 这个Bean实现了InitializingBean接口 if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) { if (logger.isTraceEnabled()) { logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'"); } if (System.getSecurityManager() != null) { try { AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> { ((InitializingBean) bean).afterPropertiesSet(); return null; }, getAccessControlContext()); } catch (PrivilegedActionException pae) { throw pae.getException(); } } else { // 因为InitializingBean接口里只有一个afterPropertiesSet方法,所以这个是由子类实现的方法。 // 作用顾名思义,在属性赋值之后做的一些善后工作。该方法允许bean实例在设置了所有bean属性后执行总体配置验证和最终初始化。 ((InitializingBean) bean).afterPropertiesSet(); } } // 如果配置了比如:@Bean(initMethod = "myInit"),指定了自定义的初始化方法,就会在这个时候执行 if (mbd != null && bean.getClass() != NullBean.class) { // 获取初始化方法名称 String initMethodName = mbd.getInitMethodName(); if (StringUtils.hasLength(initMethodName) && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) { // 这里内部实现是利用反射执行初始化方法的 invokeCustomInitMethod(beanName, bean, mbd); } } }
示例
定义一个Bean
import lombok.Getter; import lombok.Setter; import org.springframework.beans.factory.BeanNameAware; import org.springframework.beans.factory.InitializingBean; @Getter @Setter public class Apple implements BeanNameAware,InitializingBean { private String id; private String name; // 对于Aware接口的子类,实现了的方法会在Bean的初始化阶段被调用 public void setBeanName(String name) { this.id = name; } // 对于实现InitializingBean接口的Bean,需要实现这个方法,目的是属性赋值之后做的一些善后工作 public void afterPropertiesSet() throws Exception { System.out.println("Do Anything"); this.name = "我这里设置了属性B"; } // 自定义的Bean初始化方法 public void myInitMethod(){ System.out.println("Do Something"); } }
配置类
import com.entity.Apple; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class Config { @Bean(initMethod = "myInitMethod") public Apple apple(){ Apple apple = new Apple(); apple.setName("我这里设置了属性A"); return apple; } }
运行
import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class Main { public static void main(String[] args){ ApplicationContext app = new AnnotationConfigApplicationContext(Config.class); } }
如果你打断点,你会在这里拦截到我们配置影响的第一个点【Aware接口】
进入方法,会执行我们定义的setBeanName方法(这样,我们实现了BeanNameAware接口的Bean就能获取到自己的Bean名称)
----------------
接下来到第二个部分(InitializingBean接口)
进入方法,先执行我们定义的 afterPropertiesSet
----------
然后到第三部分,执行我们定义的自定义初始化方法。
初始化部分总结:
1. 如果Bean实现了Aware接口,则会执行其中的方法(方法只有一个)。实际应用比如:写一个实现ApplicationContextAware接口的工具类,来获取当前应用程序上下文。进而手动getBean。
2. 执行初始化之前的后置处理器。
3. 初始化:① 如果Bean实现了 InitializingBean 接口,则会执行 afterPropertiesSet。 ② 如果Bean指定了自定义的初始化方法,则会执行此方法。
4. 执行初始化之后的后置处理器。
思考:如果只是一个普通的Bean,则不会执行这么多逻辑。这些额外的处理都是为了应付一些复杂的场景,这里也能体会到作者的用意——扩展性。
☆☆☆【总结:Bean实例化过程,主要过程全部体现在AbstractAutowireCapableBeanFactory类里】☆☆☆
☆☆☆【销毁Bean】☆☆☆
如果前面创建单例出现了异常,就会执行销毁操作。
if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, () -> { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { // 显式地从单例缓存中删除实例:它可能被创建过程提前暴露放在那里,以允许循环引用解析。 // 还要删除所有接受该bean临时引用的bean。 destroySingleton(beanName); throw ex; } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); }
如果你想打断点到这一行,只需要在Apple实体类里加一句话:
打断点能捕获到
// 先执行:org.springframework.beans.factory.support.DefaultListableBeanFactory#destroySingleton public void destroySingleton(String beanName) { // 执行父类的逻辑 super.destroySingleton(beanName); // 更新manualSingletonNames集合,从中删除beanName removeManualSingletonName(beanName); // 清除所有按照Type获取的BeanName缓存【this.allBeanNamesByType.clear(); this.singletonBeanNamesByType.clear();】 clearByTypeCache(); }
父类逻辑
// org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#destroySingleton public void destroySingleton(String beanName) { // 删除所有此beanName注册的Bean缓存(singletonObjects、singletonFactories、earlySingletonObjects、registeredSingletons) removeSingleton(beanName); // 销毁相应的DisposableBean实例 DisposableBean disposableBean; synchronized (this.disposableBeans) { // 从存储一次性Bean的LinkedHashMap集合中删除此beanName disposableBean = (DisposableBean) this.disposableBeans.remove(beanName); } // 执行删除 destroyBean(beanName, disposableBean); }
destroyBean
protected void destroyBean(String beanName, @Nullable DisposableBean bean) { // Trigger destruction of dependent beans first... Set<String> dependencies; synchronized (this.dependentBeanMap) { // Within full synchronization in order to guarantee a disconnected Set // 从依赖Map中移除并获取依赖此bean的集合 dependencies = this.dependentBeanMap.remove(beanName); } if (dependencies != null) { if (logger.isTraceEnabled()) { logger.trace("Retrieved dependent beans for bean '" + beanName + "': " + dependencies); } // 如果存在依赖,则递归删除所有依赖这个beanName的所有bean // 这个地方白话解释一下:母猫死亡(发生了异常),那么母猫影响的是所有依赖母猫的小猫(Bean) for (String dependentBeanName : dependencies) { destroySingleton(dependentBeanName); } } // Actually destroy the bean now... // 删除一次性的bean if (bean != null) { try { bean.destroy(); } catch (Throwable ex) { if (logger.isWarnEnabled()) { logger.warn("Destruction of bean with name '" + beanName + "' threw an exception", ex); } } } // 销毁当前Bean所包含的bean Set<String> containedBeans; synchronized (this.containedBeanMap) { // Within full synchronization in order to guarantee a disconnected Set containedBeans = this.containedBeanMap.remove(beanName); } if (containedBeans != null) { // 如果包含其它bean,则递归删除 // 这个地方白话解释一下:母猫死亡(发生了异常),母猫所包含的所以东西比如粑粑(Bean),都要回归大自然。 for (String containedBeanName : containedBeans) { destroySingleton(containedBeanName); } } // 从其他bean的依赖项中移除被破坏的bean。这里是看一下dependentBeanMap中余下的value里是否含有当前beanName synchronized (this.dependentBeanMap) { for (Iterator<Map.Entry<String, Set<String>>> it = this.dependentBeanMap.entrySet().iterator(); it.hasNext();) { Map.Entry<String, Set<String>> entry = it.next(); Set<String> dependenciesToClean = entry.getValue(); dependenciesToClean.remove(beanName); if (dependenciesToClean.isEmpty()) { it.remove(); } } } // 删除bean准备好的依赖项信息。 this.dependenciesForBeanMap.remove(beanName); }
主要的销毁包含:
1. 销毁所有直接依赖此bean的bean(递归删除)
2. 如果存在的话,删除一次性注册的bean
3. 销毁此bean包含的所有bean(递归删除)
4. 遍历dependentBeanMap的value,看是否存在此bean
5. 删除自己已准备好的依赖项信息
这里涉及三个集合
/** 我拥有的人:key=我,value=我拥有的人 */ private final Map<String, Set<String>> containedBeanMap = new ConcurrentHashMap<>(16); /** 别人依赖我:key=我,value=依赖我的人 */ private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64); /** 我依赖别人:key=我,value=我依赖的人 */ private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);
图解一下
7. 创建多实例bean
// 原型模式 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); } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } protected void beforePrototypeCreation(String beanName) { // prototypesCurrentlyInCreation是一个本地线程变量,存储当前正在创建的多实例Bean Object curVal = this.prototypesCurrentlyInCreation.get(); if (curVal == null) { // 如果当前线程没有创建任务,则设置为当前BeanName this.prototypesCurrentlyInCreation.set(beanName); } else if (curVal instanceof String) { // 如果当前存储的变量是String类型,则新建一个Set集合,存储这个String变量以及我们将要创建的beanName Set<String> beanNameSet = new HashSet<>(2); beanNameSet.add((String) curVal); beanNameSet.add(beanName); // 存储进线程本地变量 this.prototypesCurrentlyInCreation.set(beanNameSet); } else { Set<String> beanNameSet = (Set<String>) curVal; // 转换成Set集合,然后把当前beanName添加进去 beanNameSet.add(beanName); } } protected void afterPrototypeCreation(String beanName) { // 获取线程本地变量 Object curVal = this.prototypesCurrentlyInCreation.get(); // 如果是String类型,直接移除 if (curVal instanceof String) { this.prototypesCurrentlyInCreation.remove(); } else if (curVal instanceof Set) { // 如果是Set集合,先移除Set集合中的beanName Set<String> beanNameSet = (Set<String>) curVal; beanNameSet.remove(beanName); // 如果集合为空,才去移除线程本地变量 if (beanNameSet.isEmpty()) { this.prototypesCurrentlyInCreation.remove(); } } }
与单例模式不同的是创建前后有个处理的过程,看过程
1. 创建之前(目的是把任务[beanName]放进本地线程变量中)
线程本地变量获取为空,则直接设置成当前beanName。
获取到线程本地变量,并且类型为String,则新建一个Set集合,将新老变量添加到集合中,最后设置成线程本地变量。
获取到线程本地变量,类型是Set集合,则先做类型转换,然后添加当前的beanName到集合中,最后设置成线程本地变量。
2. 创建Bean,在doCreateBean方法中有这么一行,如下:
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
目的是用来检测循环依赖,添加到相应的缓存中,同时它是仅仅针对单例Bean。而多实例Bean的创建不会有这个过程的。
3. 创建之后(目的是把任务[beanName]从本地线程变量中移除)
如果获取到的变量是String类型,证明只有这一个任务,直接执行remove即可。
如果获取到的变量类型是Set集合类型,证明不止当前一个任务,要把当前任务从Set集合中删除;然后再判断Set集合是否为空,为空才会执行remove方法。
8. 在指定的scope(作用域)上实例化bean
这里呢,与前面两种不同的地方仅仅是多了个获取Scope的过程,其他部分都不是事。
-
☆ 扩展——IOC容器的关闭
不卖关子直接上,Java应用程序里可以添加关闭钩子。
public static void main(String[] args){ Runtime.getRuntime().addShutdownHook(new Thread(() -> { System.out.println("关闭之前我要优雅的处理资源"); })); }
这样,当以下情况会触发
1. 程序正常退出
2. 使用System.exit()
3. 终端Ctrl+C
4. 系统关闭
5. Kill pid命令干掉进程(不是kill -9 pid)
同样,在Spring里也是这样做的(org.springframework.context.support.AbstractApplicationContext#registerShutdownHook)
public void registerShutdownHook() { if (this.shutdownHook == null) { this.shutdownHook = new Thread("SpringContextShutdownHook") { public void run() { synchronized(AbstractApplicationContext.this.startupShutdownMonitor) { AbstractApplicationContext.this.doClose(); } } }; Runtime.getRuntime().addShutdownHook(this.shutdownHook); } } /** @deprecated */ @Deprecated public void destroy() { this.close(); } public void close() { Object var1 = this.startupShutdownMonitor; synchronized(this.startupShutdownMonitor) { this.doClose(); if (this.shutdownHook != null) { try { Runtime.getRuntime().removeShutdownHook(this.shutdownHook); } catch (IllegalStateException var4) { ; } } } }
当然Spring已经写好了,不用我们去管。但是我们遇到一些业务场景可能会用到,现有框架比如Dubbo,听说就是利用这个东西实现优雅停机的。
总结
实际上Spring的重点可以说有两部分
1. 容器(IOC)创建过程:
ApplicationContext app = new AnnotationConfigApplicationContext(Config.class);2. Bean加载过程(也可以说是Bean的实例化过程):
app.getBean("user");
这两部分并不是井水不犯河水,因为容器创建过程,就涉及到单实例Bean的初始化过程了。
如果作用域是 Singleton,那么在容器创建的时候就会初始化,后面你getBean会直接返回缓存中的实例,生命周期交给容器处理。
如果作用域是 Prototype,那么每次调用getBean都会创建一个新的实例,生命周期交给调用者。
另外你还能发现,在Bean的实例化过程遇到的问题很多都是面试问的问题。比如:
BeanFactory和FactoryBean的区别?
Spring如何解决循环依赖的?
Bean的生命周期?等等
由于这部分内容比较多且复杂,一部分是年前写的,一部分是在老家写的,用的测试代码可能不一样,但是不影响Spring代码的思路。