本文将介绍基于AnnotationConfigApplicationContext的Bean加载过程的详细情况,特别是关于SpringVersion5.2.0的相关信息。我们将通过案例分析、数据研究等
本文将介绍基于AnnotationConfigApplicationContext的Bean加载过程的详细情况,特别是关于Spring Version 5.2.0的相关信息。我们将通过案例分析、数据研究等多种方式,帮助您更全面地了解这个主题,同时也将涉及一些关于2、AnnotationConfigApplicationContext、AnnotationConfigApplicationContext ad has not been refreshed yet 报错、AnnotationConfigApplicationContext和AnnotationConfigEmbeddedWebApplicationContext、AnnotationConfigApplicationContext和父上下文的知识。
本文目录一览:- 基于AnnotationConfigApplicationContext的Bean加载过程(Spring Version 5.2.0)(annotation-specified bean)
- 2、AnnotationConfigApplicationContext
- AnnotationConfigApplicationContext ad has not been refreshed yet 报错
- AnnotationConfigApplicationContext和AnnotationConfigEmbeddedWebApplicationContext
- AnnotationConfigApplicationContext和父上下文
基于AnnotationConfigApplicationContext的Bean加载过程(Spring Version 5.2.0)(annotation-specified bean)
建立个实体类
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代码的思路。
2、AnnotationConfigApplicationContext
Time is changing. 艺术的 Spring。
技术发展的脚步不等人,随着版本的更迭,一代版本一代神(dota 以前解说常说的,还记得那些 ID 号吗?357、820、599、zhou 神、ldd、buring、pis 等),游戏如此,技术如此,人生未必不如此。
1、BeanFactory VS ApplicationContext
以下是官网中的一段话,开山之作,在 spring framework- core technologies 前 1000 字中。
The org.springframework.beans
and org.springframework.context
packages are the basis for Spring Framework’s IoC container. (First blood:beans 和 context 包是 Spring IOC 容器的基础),以下这张图很多人肯定看过,但思考一下正确性与否呢?... 图肯定是正确的,那么上面的这句英文正确吗?... 个人理解,如果从 maven 的 jar 包依赖中可以看出,context(依赖 beans 和 core),expression(依赖 core)。
基础应用中,只需要依赖 context jar 包即可。
The BeanFactory
interface provides an advanced configuration mechanism capable of managing any type of object. (BeanFacroty 接口提供了一种高级配置机制,能够管理各种类型 object)
接口的目的是定义一种规范,最终如何具体实现及落地要看最终的实现类。API 文档中说到 “BeanFactory :The root interface for accessing a Spring bean container. ” ,其实也很好理解,见名思意。
ApplicationContext
is a sub-interface of BeanFactory
. (Application 是 BeanFactory 的子接口),从类图结构中,可看到 ApplicationContext 同样是一个接口,对 BeanFactory 进行了很多的扩展。
It adds:
-
Easier integration with Spring’s AOP features
-
Message resource handling (for use in internationalization)
-
Event publication
-
Application-layer specific contexts such as the
WebApplicationContext
for use in web applications.
In short, the BeanFactory
provides the configuration framework and basic functionality, and the ApplicationContext
adds more enterprise-specific functionality. The ApplicationContext
is a complete superset of the BeanFactory
and is used exclusively in this chapter in descriptions of Spring’s IoC container.
2、ApplicationContext 的实现类
Several implementations of the ApplicationContext
interface are supplied with Spring.
In stand-alone applications, it is common to create an instance of ClassPathXmlApplicationContext
or FileSystemXmlApplicationContext
.
While XML has been the traditional format for defining configuration metadata, you can instruct the container to use Java annotations or code as the metadata format by providing a small amount of XML configuration to declaratively enable support for these additional metadata formats.
Application 有很多的实现类,都是针对各种不同的实际用途与情况,但基本的配置 metadata 信息有 3 种方式: XML-based metadata 、 Annotation-based configuration(Spring2.5 版本开始支持) 、 Java-based configuration(Spring3.0 版本开始支持)。后 2 种混合使用是现在最流行的方式。
其中现在最常用的是 AnnotationConfigApplicationContext,以后会经常用到。
AnnotationConfigApplicationContext ad has not been refreshed yet 报错
AnnotationConfigApplicationContext ad has not been refreshed yet 报错
踩坑,这个报错几次后,报错提示端口占用,但是服务明明没启动,也没有启动占用该端口的服务,更改端口后依然报错端口占用
可能是这样的,启动多次springboot项目后导致该springboot项目已经存在电脑内存中,idea上面关掉项目并不能杀死该程序
解决办法:cmd 查询电脑端口占用,找到占用该端口的程序pid杀死该程序。
AnnotationConfigApplicationContext和AnnotationConfigEmbeddedWebApplicationContext
- 博客分类:
- spring boot
在以前的spring项目中,会有两个WebApplicationContext,一个是parent,从applicationContext.xml里加载的,一个是child,从servlet-context.xml里加载的。
两者是继承关系,child WebApplicationContext 可以通过getParent()函数获取到root WebApplicationContext。也就是说,我们常常通过listener初始化parent,并component-scan扫描非controller类。而通过servlet初始化child,只扫描controller类。这样便于在child可注入parent中的bean,反之就不行。
在spring boot中,好像只选择下面的其中之一:
1、AnnotationConfigApplicationContext是spring框架的多种应用上下文之一,位于spring-context.jar。使用AnnotationConfigApplicationContext可以实现基于Java的配置类加载Spring的应用上下文.避免使用application.xml进行配置。
2、AnnotationConfigEmbeddedWebApplicationContext是spring boot中的WebApplicationContext。
AnnotationConfigApplicationContext和父上下文
我在尝试使用定义上下文层次结构时遇到问题AnnotationConfigApplicationContext
。
问题是在内部定义模块上下文beanRefContext.xml
并使用另一个上下文(基于XML / Annotated)设置’parent’属性时。
例:
模块A中的beanRefContext.xml
<bean id =“ moduleA_ApplicationContext”
class =“ org.springframework.context.support.ClassPathXmlApplicationContext”>
<property name =“ configLocations”>
<列表>
<value> classpath:db-context.xml </ value>
</ list>
</ property>
</ bean>
db-context.xml
<bean id =“ dataSource”
class =“ org.apache.commons.dbcp.BasicDataSource”
destroy-method =“ close”
p:driverClassName =“ org.h2.Driver”
p:url =“ jdbc:h2:mem:testdb; DB_CLOSE_DELAY = -1; MODE = MySQL; TRACE_LEVEL_SYSTEM_OUT = 2” />
<!-休眠会话工厂->
<bean name =“ sessionFactory”
class =“ org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean”>
<property name =“ dataSource” ref =“ dataSource” />
<property name =“ useTransactionAwareDataSource” value =“ true” />
<property name =“ packagesToScan”>
<列表>
<value> com.example.model </ value>
</ list>
</ property>
<property name =“ hibernateProperties”>
<!-冬眠道具->
</ property>
</ bean>
模块B中的beanRefContext.xml
<bean id =“ moduleB_ApplicationContext”
class =“ org.springframework.context.annotation.AnnotationConfigApplicationContext”>
<property name =“ parent” ref =“ moduleA_ApplicationContext” />
<constructor-arg>
<列表>
<value> com.example.dao </ value>
</ list>
</ constructor-arg>
</ bean>
冬眠道
FooHibernateDao类实现FooDao {
@Autowired
@Qualifier(“ sessionFactory”)
私有SessionFactory sessionFactory;
// CRUD方法
}
模块B应用程序上下文无法找到在模块A应用程序上下文中定义的bean。
从代码AnnotationConfigApplicationContext
看,扫描过程似乎没有使用父对象作为解析bean的参考。
我有做错什么吗,或者使用注释配置无法创建层次结构?
我们今天的关于基于AnnotationConfigApplicationContext的Bean加载过程和Spring Version 5.2.0的分享就到这里,谢谢您的阅读,如果想了解更多关于2、AnnotationConfigApplicationContext、AnnotationConfigApplicationContext ad has not been refreshed yet 报错、AnnotationConfigApplicationContext和AnnotationConfigEmbeddedWebApplicationContext、AnnotationConfigApplicationContext和父上下文的相关信息,可以在本站进行搜索。
本文标签: