Bean的加载
spring的bean的加载是一个复杂的过程,本文旨在从大局上看spring到底在加载时做了些什么,然后再进行细节分析。
首先,在看源码之前要先去阅读几个关键的类,来帮助阅读
1:BeanWrapper,这个接口都有些什么功能呢,我们从他的uml图中看一下。
主要实现了3个功能
- 1.属性的访问和存储
- 2.属性编辑器注册表
- 3.类型转换
这个接口的实现类很朴实,主要的目的就是通过反射来读写属性,我们通常理解的Bean的生成是直接知道了class然后通过forname反射出来的bean,但这种方法相当于将代码写死了,beanWrapper是根据配置文件来动态生成的,他每一个属性都是通过TypeConvert进行转换然后反射出来,形成了一个beanwrapper,这个beanWrapper和你生命的bean的属性类型都是一模一样的,所以这就是我们得到的bean。读写beanWrapper的property的方法源码如下,感兴趣的同学可以再深入研究下。
@Override
@Nullable
public Object getValue() throws Exception {
final Method readMethod = this.pd.getReadMethod();
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
ReflectionUtils.makeAccessible(readMethod);
return null;
});
try {
return AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () ->
readMethod.invoke(getWrappedInstance(), (Object[]) null), acc);
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
ReflectionUtils.makeAccessible(readMethod);
return readMethod.invoke(getWrappedInstance(), (Object[]) null);
}
}
@Override
public void setValue(final @Nullable Object value) throws Exception {
final Method writeMethod = (this.pd instanceof GenericTypeAwarePropertyDescriptor ?
((GenericTypeAwarePropertyDescriptor) this.pd).getWriteMethodForActualAccess() :
this.pd.getWriteMethod());
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
ReflectionUtils.makeAccessible(writeMethod);
return null;
});
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () ->
writeMethod.invoke(getWrappedInstance(), value), acc);
}
catch (PrivilegedActionException ex) {
throw ex.getException();
}
}
else {
ReflectionUtils.makeAccessible(writeMethod);
writeMethod.invoke(getWrappedInstance(), value);
}
}
}
2:我们要了解的是AccesssController,这个是和权限有关的了,要知道,除了native代码,其他代码都是有自己的域的,还有一部分外来代码以前是在沙箱中的,这使得代码运行的权限是不一样的,而AccessController就是用来判断权限并授权的,具体的判断机制就不详细说了,因为这不是重点,你所需要知道的只有两个方法
1:checkPermission(Permission perm)
Perm你可以理解为一个权限map,然后checkPermission就是如其名,检查这个映射是否符合规则,如果符合,就进行授权。
2:doPrivileged(PrivilegedAction action);
这个方法就牛逼了啊,临时授权!就是在这个方法内执行的东西,拥有所有权限,比如我们底层的反射,首先要开通反射权限,然后要开通反射方法执行权限。在上面set源码中有很好的体现。有了这些基础知识,你可以开心的进入bean的加载了。
3:BeanFactory和FactoryBean
我最开始看到这两个东西时候的想法是,是不是写错了,后来……
没错,这TMD就是两个东西。下面来说明一下他俩的关系。
BeanFactory就是spring最关键的最核心的一个类,我记得有人这样比喻IOC,很形象,Bean的Instance就是球,Bean就是造球的模具,IOC是一个盒子,BeanFactory就是造造球模具的工具,而FactoryBean是一个特殊的造球的模具,特殊的Bean,因为他实现了FactoryBean<T>
。我们通常从bean中得到的本应该是bean,但是FactoryBean得到的却是getObject(无参,具体逻辑子类实现)方法中的bean。
而我们说的beanFactory的作用就是实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。他是SpringIOC的核心接口。
而我们获取bean的方法就是BeanFactory的getObject(有参,类的名字之类的);中二点的话你可以理解为万物起源。
spring程序员的编码风格
1:单一职责,大部分的类都只完成自己的工作,很少有身兼两职的,
2:大部分的方法中只完成大框逻辑,而细节由另一个方法进行封装。
3:看似是执行逻辑的create……(),resolve……()方法实际上是进行前戏准备,而真正核心的逻辑由do……()开头的方法执行,没错,到这里你就该提起精神了。
阅读源码之大局观
准备工作大致说完了,我们来看一下spring加载bean的时候,从大局观上看,他都做了些什么。
时序图这种东西,我画起来太丑了,就不画了,我就分条解说吧。
1:AbstarctBeanFactory的getBean()中的doGetBean(),
- 获取Bean真正的名字
- 从缓存中取bean
- 如果取到了,判断是不是FactoryBean,是就getObject(),不是就直接返回
- 如果没取到就进行下一步
- 检查这个BeanFactory中是否有BeanDefinition,如果没有就去查他的父类
- 看看是不是只是检查类型,如果不是就在createBean的那个map中标记现在老子要开始创建类了。
- 上一篇Spring源码解析(一)文章中,获取到的RootBeanDefinition有了用武之地。以下全都以mbd来表示
- 先看看这个mbd中的dependon属性,检查一下是否有依赖的bean,有就先创建这个依赖bean。然后注册到注册表(Map)中,
- 根据不同的域来创建bean的实例,然后检查是不是FactoryBean。
- 最后如果需要bean的类型转换,就进行转换。
然后单说倒数第二步创建实例。
- 以单例为例,因为是共享bean,所以首先还是先从缓存中取,有就判断,没有就继续。
- 然后标记一下我这要开始bean创建实例啦
- 开始创建bean中……
- 检查mbd中是否有需要重写的方法。如果有就在重写前标记个false,重写后标记为true
- 初始化bean的前后插入postProcessor
- 创建个BeanWrapper,然后从缓存中取,取到返回,没取到继续。
- 检查参数,然后选择InstantiationStrategy,
默认是CglibSubclassingInstantiationStrategy()
来初始化Bean,然后通过反射来获取bean的所有构造器,然后按照构造器参数从多到少,从public构造器到private构造器的是顺序排序,根据参数的类型,及数量来选择初始化bean的构造器。 - 然后根据构造器,反射构造出bean。
- mbd的判断,如果有父类,融合在父类中的属性。
- 判断是否支持循环依赖,如果支持,就暴露beanFactory在map中。
- 初始化bean的实例。将mbd的属性以反射形式注入生成的beanInstance;
- 创建完成后删除开始创建bean标记
结合源码细节分析
从getBean说起
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
// 由于我们会给bean设置一些别名方便使用,所以这一步就是要获取bean的权威的,真正的名字。
final String beanName = transformedBeanName(name);
Object bean;
//从缓存map中获取单例模式的实例。
Object sharedInstance = getSingleton(beanName);
//如果能取到实例,且传入的参数为空。就进行验证后返回。
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
//检查是不是FactoryBean
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
//如果没有从缓存中拿到,就继续。
else {
// 判断是否已经创建这个bean,是否是在循环依赖.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 检查是否有beanDefinition在这个BeanFactory.
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 如果没找到BeanDefinition,就去找他的父类。
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
//递归调用doGetBean();
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// 委派给代参的父类。
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// 委派给无参的父类。
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
//如果不只是类型检查,我们以mergedBeanDefinitions作为同步锁,
//在alreadyCreated这个Set中添加这个bean开始创建了,
//然后从锁住的的这个Map中移除RootBeanDefinition。
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
//这里就不打开说了,这个方法的主要作用就是获取一个RootBeanDefinition。
//先从mergedBeanDefinitions缓存Map获取,缓存如果没有,就根据beanName去beanDefinitionMap这个缓存中去寻找。
//然后以mergedBeanDefinitions缓存Map为锁进行融合。
//首先通过getParentName()检查有没有父类
//如果有,就递归调用getMergedBeanDefinition(parentName)这个方法
//如果没有就进行属性克隆。
//根据Override属性进行重写
//根据rb中读取出来的域配置来设置域属性。
//返回mbd
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 检查是否有依赖的bean,如果有就引入下一个栈帧,
// 先去加载被依赖的bean,递归调用AbstractFactoryBean的getBean(String beanName);
// 然后将依赖关系注册到依赖map中。
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);
}
}
}
//根据不同的scope策略创建实例
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;
}
});
//检查是否是FactoryBean
bean = 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);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
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;
}
}
//检查需要的type是否是实例中创建出来的type,如果不是要进行类型转换。
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.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
然后我们将根据不同的域创建实例拿出来单说
以单例为例子。
if (mbd.isSingleton()) {
//这个getSingleton()的参数是String类型的BeanName,
//ObjectFactory类型的一个匿名对象。既然是factory
//就会实现getBean()方法
//而return createBean(beanName, mbd, args);就是回调的方法
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);
}
插一句说几个map
/** 根据beanName缓存bean真正创建的实例的map */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** 根据BeanName缓存bean的factory的map */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/** 根据beanName缓存bean实例,这个实例与上面的实例不太一样, */
/** 因为这个是由为了解决依赖循环提早暴露出来的factory通过getObject获取的实例,属性未经填充的 */
/** 所以这里缓存的是为了解决依赖循环而生成的bean实例 */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
/** 将是单例的bean注册在这里。 */
private final Set<String> registeredSingletons = new LinkedHashSet<>(256);
/** 当我们开始创建bean,就在这里标记上我这个bean已经开始创建了,防止循环依赖创建 */
private final Set<String> singletonsCurrentlyInCreation =
Collections.newSetFromMap(new ConcurrentHashMap<>(16));
之后,这里我们打开getSingleton()方法。
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
//惯例同步操作,以对象map为锁。
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 + "'");
}
//这个方法看似只是一个判断,但是利用了&&符号的短路原理,进行了两个操作
//1:检查inCreationCheckExclusions中是否有这个bean
//2:在singletonsCurrentlyInCreation这个set缓存中加入了这个bean的名字。
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) {
// Has the singleton object implicitly appeared in the meantime ->
// if yes, proceed with it since the exception indicates that state.
singletonObject = this.singletonObjects.get(beanName);
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;
}
//和之前的before相对应
//将beanname从map中移除。
afterSingletonCreation(beanName);
}
//之前标记的开关位。
if (newSingleton) {
//如果是新建的单例,就把单例添加到当前锁的缓存map中,
//然后移除在创建过程中在缓存中添加的获取当前bean的BeanFactory对象
//然后移除掉为了解决循环依赖而添加在缓存中的单例对象
//然后在单例注册map中添加单例对象。
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
来看匿名对象实现ObjectFactory接口的getObject方法,如下所示,这里只实现了一个createBean方法和校验是否是factory的方法,
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);
}
最前面说过,createBean方法对于docreateBean方法来说就是前戏,现在我们来看看createBean都做了些什么
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
//确认bean在这里被真正的解析了。在动态解析的class中进行那些不能在mbd中储存的bd的克隆
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// 为方法的覆写做准备.
try {
//在这里spring做了一些提高效率的操作,在判断当前方法有父类方法时,在父类方法上标记了不重写。
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// 在bean初始化之前调用后处理器链。这是spring的扩展功能能实现的关键处,但这不是现在的重点。
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 {
//哎,你看关键的doCreateBean来了,我们抽出去单独说。
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("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);
}
}
在这个docreatebean中,5步走
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// 第一步:初始化通过Wrapper反射生成bean。
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
//惯例先去缓存map中找
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//要是空就执行具体的创建实例。这里的具体逻辑就是根据mbd中读取出的不同的策略也就是使用不同的代理类,
//进行动态代理,反射创建bean,将mbd中及args中的参数挨个反射成wrapper的属性。
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// 这里把后处理器链锁住,然后在这里进行最后一次的属性对象修改。
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;
}
}
// 把需要暴露出来的ObjectBean暴露出来,添加到map缓存中,用于解决循环依赖。
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// 初始化bean的实例。
Object exposedObject = bean;
try {
//进行属性填充,通过byname/bytype等方式。
populateBean(beanName, mbd, instanceWrapper);
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;
}
以上就是Spring根据Xml方式获取Bean的配置,并进行加载的全过程。