Spring Bean生命周期源码剖解

 

前言

由于本人也是刚开始学习Spring源码,欢迎各位大佬指导。

Bean对象生命周期流程图

扫描过程:

ApplicationContext创建

通过创建一个AnnotationConfigApplicationContext容器来进行分析:

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class)

点开查看这个构造器源码 

/**
	 * Create a new AnnotationConfigApplicationContext, deriving bean definitions
	 * from the given component classes and automatically refreshing the context.
	 * @param componentClasses one or more component classes — for example,
	 * {@link Configuration @Configuration} classes
	 */
	public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
		// 构造DefaultListableBeanFactory、AnnotatedBeanDefinitionReader、ClassPathBeanDefinitionScanner
		this();
		register(componentClasses);
		refresh();
	}

this()方法中,构造了两个关键的东西,一个是reader ,一个是scaner

/**
	 * Create a new AnnotationConfigApplicationContext that needs to be populated
	 * through {@link #register} calls and then manually {@linkplain #refresh refreshed}.
	 */
	public AnnotationConfigApplicationContext() {
		StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");
		// 额外会创建StandardEnvironment
		this.reader = new AnnotatedBeanDefinitionReader(this);
		createAnnotatedBeanDefReader.end();
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}

        那Spring容器的扫描是怎么进行的呢? 是的,其实就是调用了this.scanner中的scan()方法进行扫描,具体来看一下吧

scanner中的scan()方法

public int scan(String... basePackages) {
		int beanCountAtScanStart = this.registry.getBeanDefinitionCount();

		doScan(basePackages);

		// Register annotation config processors, if necessary.
		if (this.includeAnnotationConfig) {
			AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
		}

		return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
	}

        核心代码就在于这个doScan()方法,是进行真正的扫描

       核心扫描方法:doScan()

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
		Assert.notEmpty(basePackages, "At least one base package must be specified");
		Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
		for (String basePackage : basePackages) {

			Set<BeanDefinition> candidates = findCandidateComponents(basePackage);

			for (BeanDefinition candidate : candidates) {
				ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
				candidate.setScope(scopeMetadata.getScopeName());

				String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);

				if (candidate instanceof AbstractBeanDefinition) {
					postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
				}
				if (candidate instanceof AnnotatedBeanDefinition) {
					// 解析@Lazy、@Primary、@DependsOn、@Role、@Description
					AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
				}

				// 检查Spring容器中是否已经存在该beanName
				if (checkCandidate(beanName, candidate)) {
					BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
					definitionHolder =
							AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
					beanDefinitions.add(definitionHolder);

					// 注册
					registerBeanDefinition(definitionHolder, this.registry);
				}
			}
		}
		return beanDefinitions;
	}
      1. 扫描BeanDefiniton对象方法:findCandidateComponents()

         我们先进行分析findCandidateComponents()这个方法, 通过返回值我们可以得出,这个就是来扫描BeanDefinition对象。

public Set<BeanDefinition> findCandidateComponents(String basePackage) {
		if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
			return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
		}
		else {
			return scanCandidateComponents(basePackage);
		}
	}
addCandidateComponentsFromIndex(this.componentsIndex, basePackage)

一般不会走该方法,如果你自己定义了一个索引,则会进行这里的逻辑

具体源码如下:

 大体逻辑和下面 scanCandidateComponents(basePackage)类似,只是有个索引的作用,可以通过该索引直接去查找对于路径下的注解,生成bean,重点分析下面的那个方法

private Set<BeanDefinition> addCandidateComponentsFromIndex(CandidateComponentsIndex index, String basePackage) {
		Set<BeanDefinition> candidates = new LinkedHashSet<>();
		try {
			Set<String> types = new HashSet<>();
			for (TypeFilter filter : this.includeFilters) {
				// Component注解
				String stereotype = extractStereotype(filter);
				if (stereotype == null) {
					throw new IllegalArgumentException("Failed to extract stereotype from " + filter);
				}
				types.addAll(index.getCandidateTypes(basePackage, stereotype));
			}
			boolean traceEnabled = logger.isTraceEnabled();
			boolean debugEnabled = logger.isDebugEnabled();
			for (String type : types) {
				MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(type);
				if (isCandidateComponent(metadataReader)) {
					ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
					sbd.setSource(metadataReader.getResource());
					if (isCandidateComponent(sbd)) {
						if (debugEnabled) {
							logger.debug("Using candidate component class from index: " + type);
						}
						candidates.add(sbd);
					}
					else {
						if (debugEnabled) {
							logger.debug("Ignored because not a concrete top-level class: " + type);
						}
					}
				}
				else {
					if (traceEnabled) {
						logger.trace("Ignored because matching an exclude filter: " + type);
					}
				}
			}
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
		}
		return candidates;
	}

 scanCandidateComponents(basePackage)     

  思考一下,我们怎么进行扫描呢?

        (大概流程) 首先会根据路径获取该路径下的所有资源,然后在通过遍历每一个resource对象,扫描到该对象的一些注解,确认是否可以成为一个bean对象,然后在进行注入。

private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
		Set<BeanDefinition> candidates = new LinkedHashSet<>();
		try {
			// 获取basePackage下所有的文件资源
			String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
					resolveBasePackage(basePackage) + '/' + this.resourcePattern;

			Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);

			boolean traceEnabled = logger.isTraceEnabled();
			boolean debugEnabled = logger.isDebugEnabled();
			for (Resource resource : resources) {
				if (traceEnabled) {
					logger.trace("Scanning " + resource);
				}
				if (resource.isReadable()) {
					try {
						MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
						// excludeFilters、includeFilters判断
						if (isCandidateComponent(metadataReader)) { // @Component-->includeFilters判断
							ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
							sbd.setSource(resource);

							if (isCandidateComponent(sbd)) {
								if (debugEnabled) {
									logger.debug("Identified candidate component class: " + resource);
								}
								candidates.add(sbd);
							}
							else {
								if (debugEnabled) {
									logger.debug("Ignored because not a concrete top-level class: " + resource);
								}
							}
						}
						else {
							if (traceEnabled) {
								logger.trace("Ignored because not matching any filter: " + resource);
							}
						}
					}
					catch (Throwable ex) {
						throw new BeanDefinitionStoreException(
								"Failed to read candidate component class: " + resource, ex);
					}
				}
				else {
					if (traceEnabled) {
						logger.trace("Ignored because not readable: " + resource);
					}
				}
			}
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
		}
		return candidates;
	}
大致流程

大致流程如下图:https://www.processon.com/v/64db3d1028344d578df63b77

1.首先通过遍历出每个resource后,获得他们的原空间对象metadataReader对象

2.通过metadataReader对象,进行excludeFilters、includeFilters判断

3.通过后在根据metadataReader对象判断是否独立、是否是接口、是否是抽象类并且含有@Lookup注解

4.都通过后添加BeanDefinition对象

isCandidateComponent(MetadataReader metadataReader)

让我们来分析 isCandidateComponent(MetadataReader metadataReader)源码

protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
		for (TypeFilter tf : this.excludeFilters) {
			if (tf.match(metadataReader, getMetadataReaderFactory())) {
				return false;
			}
		}

		// 符合includeFilters的会进行条件匹配,通过了才是Bean,也就是先看有没有@Component,再看是否符合@Conditional
		for (TypeFilter tf : this.includeFilters) {
			if (tf.match(metadataReader, getMetadataReaderFactory())) {
				return isConditionMatch(metadataReader);
			}
		}
		return false;
	}

        定义了两个List<TypeFilter> 用来存储 includeFilter 和 excludeFilter信息,如果要是在exclude的字段,将返回false,然后不做处理,如果要是include的字段,返回结果是在于 isConditionMatch()这个方法。 

        可能大家有疑问。为什么项目中我明明什么都没指定,但是一样会产生bean对象呢?

        原因在于,Spring在初始化scaner时,添加了@component注解为默认的includeFilter字段

         大家可以在ApplicationContext的构造方法的this()方法中找到scanner的构造方法,然后一步步点进去,直到registerDefaultFilters()这个方法

        让我们再回到刚刚判断includeFilters的地方,刚刚我们提到了返回值是一个方法,让我们来分析一下该方法

shouldSkip         

进入到对应的shouldSkip(metadata, null) 

public boolean shouldSkip(@Nullable AnnotatedTypeMetadata metadata, @Nullable ConfigurationPhase phase) {
		if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) {
			return false;
		}

		if (phase == null) {
			if (metadata instanceof AnnotationMetadata &&
					ConfigurationClassUtils.isConfigurationCandidate((AnnotationMetadata) metadata)) {
				return shouldSkip(metadata, ConfigurationPhase.PARSE_CONFIGURATION);
			}
			return shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN);
		}

		List<Condition> conditions = new ArrayList<>();
		for (String[] conditionClasses : getConditionClasses(metadata)) {
			for (String conditionClass : conditionClasses) {
				Condition condition = getCondition(conditionClass, this.context.getClassLoader());
				conditions.add(condition);
			}
		}

		AnnotationAwareOrderComparator.sort(conditions);

		for (Condition condition : conditions) {
			ConfigurationPhase requiredPhase = null;
			if (condition instanceof ConfigurationCondition) {
				requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
			}
			if ((requiredPhase == null || requiredPhase == phase) && !condition.matches(this.context, metadata)) {
				return true;
			}
		}

		return false;
	}

        其实这段代码主要是判断是否有@conditonal这个注解

        如果没有的话,返回false,由于前面的返回值取得是非值,即为true,这样就正常生成了BeanDefiniton对象。

        如果有的话,会走下面的逻辑,下面的逻辑大概是将会执行conditon类的matches()方法,然后根据返回值来判断。


        扩展一下:@conditonal注解

我们通过简单的操作来看一下@conditonal注解的作用。

这是我的项目结构:

首先创建一个自己的conditon类

public class TestConditional implements Condition {
	@Override
	public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
		try {
			context.getClassLoader().loadClass("com.zhouyu.service.User");
			return true;
		} catch (ClassNotFoundException e) {
			return false;
		}
	}
}

创建一个配置类

@ComponentScan(value = "com.zhouyu")
public class AppConfig {

}

创建一个UserService类,添加Conditional注解

@Component
@Conditional(TestConditional.class)
public class UserService {

	public UserService() {
	}

	public void test(){
		System.out.println();
	}
}

然后我们通过AppConfig这个配置类来获取userService对象。

先猜测一下,肯定是能获得的,因为我们项目中有User这个类,然后TestConditonal返回的肯定是true。

// 创建一个Spring容器
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);

		UserService userService = (UserService) applicationContext.getBean("userService");
		System.out.println(userService);

运行结果:

 但如果我们修改一下 TestConditional 。让他返回false呢

public class TestConditional implements Condition {
	@Override
	public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
		try {
			context.getClassLoader().loadClass("com.zhouyu.service.User1");
			return true;
		} catch (ClassNotFoundException e) {
			return false;
		}
	}
}

我们通过加载器加载User1这个对象,首先我们的项目里并没有User1这个对象,因此一定会发生错误,也就是会返回false,让我们再看一下结果

 结果显而易见,没有找到userService这个bean对象

归根结底就是这个@conditonal注解返回的是false,返回刚刚源码的地方,是不是很容易理解刚刚的话了。


isCandidateComponent(AnnotatedBeanDefinition beanDefinition)

回到源码,继续往下走,又到了一个判断。

protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
		AnnotationMetadata metadata = beanDefinition.getMetadata();
		return (metadata.isIndependent() && (metadata.isConcrete() ||
				(metadata.isAbstract() && metadata.hasAnnotatedMethods(Lookup.class.getName()))));
	}
isIndependent:到底是顶级类还是嵌套类(静态内部类),可以独立于外部类构造
isConcrete:是否是接口
isAbstract:是否是抽象类
hasAnnotatedMethods(Lookup.class.getName()):是否有Lookup注解

都通过后就添加BeanDefinition对象


扩展@Lookup用法:

通过上面的判断,判断是否是抽象类&&是否有Lookup注解,我们不妨来测试一下。

定义UserService类为抽象类,看是否能获取bean对象

@Component
//@Conditional(TestConditional.class)
public abstract class UserService {
	@Autowired
	private User user;

	public void test(){
		System.out.println(user);
	}
}
// 创建一个Spring容器
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);

		UserService userService = (UserService) applicationContext.getBean("userService");
		userService.test();

打印结果:

但如果我们加入@Lookup注解

@Component
//@Conditional(TestConditional.class)
public abstract class UserService {
	@Autowired
	private User user;


	public void test(){
		System.out.println(user);
	}

	@Lookup("user")
	public void  a(){

	}
}

运行结果:就可以拿到这个抽象类的bean对象了

另一个用法,我们定义User对象为prototype,UserService对象为单例bean时,如果userService调用方法生成user对象时,这个user对象是否为同一个呢?

@Component
@Scope("prototype")
public class User {
}

@Component
//@Conditional(TestConditional.class)
public class UserService {
	@Autowired
	private User user;


	public void test(){
		System.out.println(user);
	}
/*
	@Lookup("user")
	public void  a(){

	}*/
}
// 创建一个Spring容器
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);

		UserService userService = (UserService) applicationContext.getBean("userService");
		userService.test();
		userService.test();
		userService.test();

打印结果:为同一个对象,原因是由于userService对象是单例的,因此不管userService是否为原型bean,只赋值一次,也就是打印的是同一个对象了

 我们修改一下代码:

@Component
//@Conditional(TestConditional.class)
public class UserService {
	@Autowired
	private User user;


	public void test(){
		System.out.println(a());
	}
	@Lookup("user")
	public User  a(){
		return null;
	}
}

打印结果:不同的bean对象

2. 扫描获得的BeanDefinition对象赋予一些默认值 postProcessBeanDefinition()
protected void postProcessBeanDefinition(AbstractBeanDefinition beanDefinition, String beanName) {
		// 设置BeanDefinition的默认值
		beanDefinition.applyDefaults(this.beanDefinitionDefaults);

		// AutowireCandidate表示某个Bean能否被用来做依赖注入
		if (this.autowireCandidatePatterns != null) {
			beanDefinition.setAutowireCandidate(PatternMatchUtils.simpleMatch(this.autowireCandidatePatterns, beanName));
		}
	}
public void applyDefaults(BeanDefinitionDefaults defaults) {
		Boolean lazyInit = defaults.getLazyInit();
		if (lazyInit != null) {
			setLazyInit(lazyInit);
		}
		setAutowireMode(defaults.getAutowireMode());
		setDependencyCheck(defaults.getDependencyCheck());
		setInitMethodName(defaults.getInitMethodName());
		setEnforceInitMethod(false);
		setDestroyMethodName(defaults.getDestroyMethodName());
		setEnforceDestroyMethod(false);
	}
3.解析@Lazy、@Primary、@DependsOn、@Role、@Description注解
static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
		AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);
		if (lazy != null) {
			abd.setLazyInit(lazy.getBoolean("value"));
		}
		else if (abd.getMetadata() != metadata) {
			lazy = attributesFor(abd.getMetadata(), Lazy.class);
			if (lazy != null) {
				abd.setLazyInit(lazy.getBoolean("value"));
			}
		}

		if (metadata.isAnnotated(Primary.class.getName())) {
			abd.setPrimary(true);
		}
		AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);
		if (dependsOn != null) {
			abd.setDependsOn(dependsOn.getStringArray("value"));
		}

		AnnotationAttributes role = attributesFor(metadata, Role.class);
		if (role != null) {
			abd.setRole(role.getNumber("value").intValue());
		}
		AnnotationAttributes description = attributesFor(metadata, Description.class);
		if (description != null) {
			abd.setDescription(description.getString("value"));
		}
	}
4.检查Spring容器中是否已经存在该beanName
protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition) throws IllegalStateException {
		if (!this.registry.containsBeanDefinition(beanName)) {
			return true;
		}
		BeanDefinition existingDef = this.registry.getBeanDefinition(beanName);
		BeanDefinition originatingDef = existingDef.getOriginatingBeanDefinition();
		if (originatingDef != null) {
			existingDef = originatingDef;
		}
		// 是否兼容,如果兼容返回false表示不会重新注册到Spring容器中,如果不冲突则会抛异常。
		if (isCompatible(beanDefinition, existingDef)) {
			return false;
		}
		throw new ConflictingBeanDefinitionException("Annotation-specified bean name '" + beanName +
				"' for bean class [" + beanDefinition.getBeanClassName() + "] conflicts with existing, " +
				"non-compatible bean definition of same name and class [" + existingDef.getBeanClassName() + "]");
	}
5.注册(注册到了BeanDefinitionMap中)
public static void registerBeanDefinition(
			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
			throws BeanDefinitionStoreException {

		// Register bean definition under primary name.
		String beanName = definitionHolder.getBeanName();
		registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

		// Register aliases for bean name, if any.
		String[] aliases = definitionHolder.getAliases();
		if (aliases != null) {
			for (String alias : aliases) {
				registry.registerAlias(beanName, alias);
			}
		}
	}

初始化非懒加载单例bean 

通过 finishBeanFactoryInitialization(beanFactory)进去,找到beanFactory.preInstantiateSingletons() 方法
public void preInstantiateSingletons() throws BeansException {
		if (logger.isTraceEnabled()) {
			logger.trace("Pre-instantiating singletons in " + this);
		}

		// Iterate over a copy to allow for init methods which in turn register new bean definitions.
		// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

		// Trigger initialization of all non-lazy singleton beans...
		for (String beanName : beanNames) {
			// 获取合并后的BeanDefinition
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);

			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				if (isFactoryBean(beanName)) {
					// 获取FactoryBean对象
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					if (bean instanceof FactoryBean) {
						FactoryBean<?> factory = (FactoryBean<?>) bean;
						boolean isEagerInit;
						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
							isEagerInit = AccessController.doPrivileged(
									(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
									getAccessControlContext());
						}
						else {
							isEagerInit = (factory instanceof SmartFactoryBean &&
									((SmartFactoryBean<?>) factory).isEagerInit());
						}
						if (isEagerInit) {
							// 创建真正的Bean对象(getObject()返回的对象)
							getBean(beanName);
						}
					}
				}
				else {
					// 创建Bean对象
					getBean(beanName);
				}
			}
		}

		// 所有的非懒加载单例Bean都创建完了后
		// Trigger post-initialization callback for all applicable beans...
		for (String beanName : beanNames) {
			Object singletonInstance = getSingleton(beanName);
			if (singletonInstance instanceof SmartInitializingSingleton) {
				StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
						.tag("beanName", beanName);
				SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
						smartSingleton.afterSingletonsInstantiated();
						return null;
					}, getAccessControlContext());
				}
				else {
					smartSingleton.afterSingletonsInstantiated();
				}
				smartInitialize.end();
			}
		}
	}

首先先了解 RootBeanDefinition ,他是后来生产的合并的BeanDefinition,比如:

	<bean id="user" class="com.zhouyu.service.User" abstract="true" scope="prototype"/>
	<bean id="userService" class="com.zhouyu.service.UserService" parent="user"/>

user是原型,userService是单例的(默认),然后userService的parent是user,那userService是单例还是原型?

ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");

		UserService userService = (UserService) applicationContext.getBean("userService");
		UserService userService1 = (UserService) applicationContext.getBean("userService");
		UserService userService2 = (UserService) applicationContext.getBean("userService");
		System.out.println(userService);
		System.out.println(userService1);
		System.out.println(userService2);

运行结果: userService采用了它父BeanDefinition的属性。然后Spring创建的时候不能更改user以及userService的属性,是采用创建了RootBeanDefinition来进行合并生成第三个BeanDefinition

并且合并的流程先不分析,感兴趣的朋友可以看看,也是挺简单。

下一步拿着合并后的BeanDefinition对象来判断是否是抽象的BeanDefinition、是否是懒加载的、是否是单例的,都通过后,才真正的创建Bean对象: getBean(beanName)

 下一步都所有的非抽象、非懒加载的单例bean创建完成后,对于实现了SmartInitializingSingleton 的接口的bean对象,执行 smartSingleton.afterSingletonsInstantiated()方法

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值