一.前言
spring作为JAVAEE最核心的框架,是每一个java开发者所必须掌握的,非常重要,本篇从一个简单例子入手,由浅入深的分析spring创建bean的全过程,目标在于彻底搞懂spring原理,方便以后整合其他框架
二.测试代码
/**
* * * @author <a href="mailto:2256222053@qq.com">zc</a>
* @Date 2022/4/3 0003 14:45
*/
@Lazy
public class CreateBean {
private String name;
private int age;
public CreateBean() {
}
public CreateBean(int age) {
this.age = age;
}
public CreateBean(String name) {
this.name = name;
}
public CreateBean(String name, int age) {
this.name = name;
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "CreateBean{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
- 一个交给spring管理的bean,为了好debug,加了一个懒加载属性
@Test
void doCreateBean(){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(CreateBean.class);
Object bean = context.getBean("createBean", "chuan", 24);
System.out.println(bean);
}
- 一个启动类,getBean是入口,开始创建bean
三. 开始获取bean:getBean()
@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
assertBeanFactoryActive();
return getBeanFactory().getBean(name, requiredType);
}
1. 判断容器的活动状态:assertBeanFactoryActive()
容器在启动的时候会设置这个状态值,具体在:AbstractApplicationContext#prepareRefresh()
2.获取beanFactory:getBeanFactory()
从beanFactory中获取bean,默认这个beanFactory是DefaultListableBeanFactory,因为AnnotationConfigApplicationContext继承了GenericApplicationContext,通过他的构造器可以发现
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
3.getBean(name, requiredType)
通过bean的名称获取bean,第二个参数是bean的类型,如果传了后面会做类型转换,否则就是Object
@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return doGetBean(name, requiredType, null, false);
}
getBean:这个类有很多getBean方法,这是使用重载的表现,但是最终都会调用doGetBean,这个方法有四个参数,分别是bean的名称name,bean的类型,创建bean时构造参数的值
四.真正获取Bean的方法:doGetBean()
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
String beanName = transformedBeanName(name);
Object beanInstance;
// Eagerly check singleton cache for manually registered singletons.
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 + "'");
}
}
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference. if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
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);
}
StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
.tag("beanName", name);
try {
if (requiredType != null) {
beanCreation.tag("beanType", requiredType::toString);
}
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
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 + "'");
}
registerDependentBean(dep, beanName);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
throw ex;
}
});
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
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);
}
beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
String scopeName = mbd.getScope();
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean '" + beanName + "'");
}
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);
}
});
beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new ScopeNotActiveException(beanName, scopeName, ex);
}
}
}
catch (BeansException ex) {
beanCreation.tag("exception", ex.getClass().toString());
beanCreation.tag("message", String.valueOf(ex.getMessage()));
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
finally {
beanCreation.end();
}
}
return adaptBeanInstance(name, beanInstance, requiredType);
}
这个方法很复杂,但是可以简要分为以下几个步骤
1. 获取bean名称
transformedBeanName()
因为可能会有前缀&,获取FactoryBean的情况,所以需要在这解析
2.尝试从缓存中获取bean
getSingleton()
3.判断这个bean是否在创建中
isPrototypeCurrentlyInCreation(beanName)
这一步目的是为了防止循环依赖
4.标记为正在创建中
markBeanAsCreated(beanName):将这个bean
5.合并Definition
getMergedLocalBeanDefinition(beanName)
通过parentName的值来判断是否有父definition,合并的目的在于保证definition的正确性,spring在每次要用definition的时候都会进行一次合并,因为有很多扩展点可以修改definition
6.检查合并后的Definition
checkMergedBeanDefinition(mbd, beanName, args);
7.获取依赖的Bean
mbd.getDependsOn();
如果不为空则会先创建依赖的bean
8.获取真正需要的Bean
getSingleton(beanName,()->{return createBean(beanName, mbd, args);})
获取一个注册好的bean,如果没有,会使用参数FactoryBean注册一个,非常重要,真正创建bean的入口,下面会详细会讲创建过程
getObjectForBeanInstance(sharedInstance, name, beanName, mbd);,如果name有前缀&,那么会返回FactoryBean的实例,如果注册的是一个FactoryBean,这里会调用getObject来返回真正的bean对象
adaptBeanInstance(name, beanInstance, requiredType);最后一步类型转换
五.获取Bean的过程: getSingleton()
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
afterSingletonCreation(beanName);
}
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
1.尝试从一级缓存中获取Bean
Object singletonObject = this.singletonObjects.get(beanName);
我们这里肯定是没有的,如果有则会直接返回
2.将这个Bean标记为创建中
beforeSingletonCreation(beanName);
里面主要操作就是将这个beanName添加进singletonsCurrentlyInCreation数组中,这个数组里面存的都是正在创建的Bean名称
3.创建Bean
singletonObject = singletonFactory.getObject();
singletonFactory是上面传过来的参数,所以这会去调用上面传过来的的createBean方法,这里使用了@FunctionalInterface函数接口,非常精髓,下面会详细分析createBean的过程
4.将这个Bean标记为已创建
afterSingletonCreation(beanName);
对应上面第二步,删除singletonsCurrentlyInCreation的这个beanName,标记他已经创建完成
5.注册Bean
addSingleton(beanName, singletonObject)
注册bean,把上面第三步创建出来的singletonObject添加进一级缓存singletonObjects和单例缓存registeredSingletons中,删除三级缓存singletonFactories和二级缓存earlySingletonObjects中key为beanName的值
六.开始创建Bean: createBean(beanName, mbd, args)
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
if (this.logger.isTraceEnabled()) {
this.logger.trace("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
Class<?> resolvedClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
try {
mbdToUse.prepareMethodOverrides();
} catch (BeanDefinitionValidationException var9) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", var9);
}
Object beanInstance;
try {
beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);
if (beanInstance != null) {
return beanInstance;
}
} catch (Throwable var10) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", var10);
}
try {
beanInstance = this.doCreateBean(beanName, mbdToUse, args);
if (this.logger.isTraceEnabled()) {
this.logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
} catch (ImplicitlyAppearedSingletonException | BeanCreationException var7) {
throw var7;
} catch (Throwable var8) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", var8);
}
}
1.加载类
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
2.标记override的属性
mbdToUse.prepareMethodOverrides();
其实就是lookup-method和replace-method两个属性,如果没有重载会记录下来,后面就不会根据参数判断是哪一个具体的方法,减少了系统开销
3,实例化之前后置处理器
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
调用所有实现了InstantiationAwareBeanPostProcessor接口的类的postProcessBeforeInstantiation方法,如果返回不为null,会接着调用所有实现了BeanPostProcessor接口的类的postProcessAfterInitialization方法,然后返回,aop就是在此处实现的,我们这里所有实现了InstantiationAwareBeanPostProcessor接口的类都是默认的,返回的都是null,所以不会执行后置处理器的after方法,会返回一个null,下面是参考代码
@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = this.determineTargetType(beanName, mbd);
if (targetType != null) {
bean = this.applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = this.applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = bean != null;
}
return bean;
}
4.判断第三步返回的bean是否为空
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
这一步比较重要,因为如果不为空会直接返回,这代表着不会执行spring创建bean的方法,比如后面的属性注入,aware接口回调,初始化前,初始化,初始化后都不会执行
5.创建Bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
真正开始创建bean的方法,spring真正干活的方法都是以do开头的,我认为这是一种很好的方法命名规则
七.真正开始创建Bean: doCreateBean(beanName, mbdToUse, args)
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = this.createBeanInstance(beanName, mbd, args);
}
synchronized(mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
} catch (Throwable var17) {
}
mbd.postProcessed = true;
}
}
boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
if (earlySingletonExposure) {
this.addSingletonFactory(beanName, () -> {
return this.getEarlyBeanReference(beanName, mbd, bean);
});
}
Object exposedObject = bean;
this.populateBean(beanName, mbd, instanceWrapper);
exposedObject = this.initializeBean(beanName, exposedObject, mbd);
if (earlySingletonExposure) {
Object earlySingletonReference = this.getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
} else if (!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {
String[] dependentBeans = this.getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet(dependentBeans.length);
String[] var12 = dependentBeans;
int var13 = dependentBeans.length;
for(int var14 = 0; var14 < var13; ++var14) {
String dependentBean = var12[var14];
if (!this.removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
}
}
}
try {
this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
return exposedObject;
} catch (BeanDefinitionValidationException var16) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);
}
}
1.创建bean实例
createBeanInstance(beanName, mbd, args)
2.执行Definition的后置处理器
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName)
spring在这一步实现了对元注解的解析
如果这个bean是单例的且正在创建中,则会加入三级缓存中,目的是暴露bean的引用,解决循环依赖:this.addSingletonFactory(beanName, () -> {
return this.getEarlyBeanReference(beanName, mbd, bean);
})
3.属性填充
populateBean(beanName, mbd, instanceWrapper);
4.初始化bean
initializeBean(beanName, exposedObject, mbd);
5.注册Bean的销毁方法
registerDisposableBeanIfNecessary(beanName, bean, mbd)
到这才真正开始进入创建bean的流程,流程中的每一步都非常复杂,建议还是很模糊的同学自重,避免走火入魔想对我人身攻击的。下面就每个方法重要的点一一解析,严格按照方法的执行先后顺序来说明
1.1 创建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());
}
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
if (mbd.getFactoryMethodName() != null) {
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) {
return autowireConstructor(beanName, mbd, null, null);
}
else {
return instantiateBean(beanName, mbd);
}
}
// Candidate constructors for autowiring?
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// Preferred constructors for default construction?
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}
// No special handling: simply use no-arg constructor.
return instantiateBean(beanName, mbd);
}
1. 通过Supplier接口创建Bean实例
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
我们这里没有使用这个方式,这种方式需要在注册的时候提供如下
public class C implements Supplier<C> {
@Override
public C get() {
System.out.println("Supplier");
return new C();
}
}
/**
* 自定义实例化方法{@link java.util.function.Supplier#get}
* 源码调用{@link org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance}
*/@Test
void supplier(){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.registerBean(C.class,new C());
context.refresh();
context.getBean("c");
}
2. 通过静态工厂或实例工厂创建Bean实例
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
我们这没有使用工厂的方式,这两种使用方式如下:
实例工厂:
public class FactoryBeanService {
private static Bean bean = new Bean();
private FactoryBeanService() {}
public Bean createInstance() {
System.out.println("实例工厂方法实例化bean");
return bean;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="serviceLocator"
class="com.youlai.laboratory.spring.create.FactoryBeanService"
/>
<bean id="factoryBeanService"
factory-bean="serviceLocator"
factory-method="createInstance"
/>
</beans>
@Test
void factoryBean(){
ClassPathXmlApplicationContext xmlApplicationContext = new ClassPathXmlApplicationContext("classpath:spring/create/FactoryBean.xml");
}
静态工厂:
public class FactoryClassService {
private static Bean bean = new Bean();
private FactoryClassService() {}
public static Bean createInstance() {
System.out.println("静态工厂方法实例化bean");
return bean;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="factoryClassService"
class="com.youlai.laboratory.spring.create.FactoryClassService"
factory-method="createInstance"/>
</beans>
@Test
void factoryMethod(){
ClassPathXmlApplicationContext xmlApplicationContext = new ClassPathXmlApplicationContext("classpath:spring/create/FactoryClass.xml");
}
3. 推断可用的构造器
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName)
这一步比较重要,下面会详细分析
@Override
@Nullable
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
throws BeanCreationException {
// Let's check for lookup methods here...
if (!this.lookupMethodsChecked.contains(beanName)) {
if (AnnotationUtils.isCandidateClass(beanClass, Lookup.class)) {
try {
Class<?> targetClass = beanClass;
do {
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Lookup lookup = method.getAnnotation(Lookup.class);
if (lookup != null) {
Assert.state(this.beanFactory != null, "No BeanFactory available");
LookupOverride override = new LookupOverride(method, lookup.value());
try {
RootBeanDefinition mbd = (RootBeanDefinition)
this.beanFactory.getMergedBeanDefinition(beanName);
mbd.getMethodOverrides().addOverride(override);
}
catch (NoSuchBeanDefinitionException ex) {