在Spring---组件扫描一文中,我们了解到Spring在容器启动时,是如何扫描到带有@Component注解的类并将其添加到beanDefinitionMap之中的。存在于beanDefinitionMap之中的只是所有bean的定义,这些定义包括“是否单例”,“是否懒初始化”,“类元数据信息”等等。当我们需要从容器中获取一个bean时,便会根据该bean定义信息,实例化bean对象,接下来我们看看整个实现过程。
我们会从源码角度分析,这里假设我们有:
组件类Task和TimerTask
@Component
public class Task {
public void run() {
}
}
@Component
public class TaskTimer {
@Autowired
Task task;
public void task() {
task.run();
}
}
工厂bean类
@Component
public class TimerFactoryBean implements SmartFactoryBean {
@Override
public Object getObject() throws Exception {
return new TaskTimer();
}
@Override
public Class> getObjectType() {
return null;
}
@Override
public boolean isEagerInit() { return false; }
}
我们将通过这两个类分析以下两个问题:
首先一切通过名称获取Bean的入口都是AbstractBeanFactory.doGetBean方法,无论你通过ApplicationContext还是BeanFactory,
接下来我们看看该方法干了什么(请自行打开源码跟着以下步骤分析):
在Spring容器中组件分为两种:
1.普通组件
即普通Bean,如上面的Task和TimerTask,我们直接可以通过名称从容器中获取到该Bean。
TimerTask timerTask = (TimerTask) context.getBean("timerTask");
2.工厂组件
即FactoryBean,如上面的TimerFactoryBean,这个Bean我们是无法通过Bean名称直接获取的。如下:
TimerFactoryBean timerFactoryBean = (TimerFactoryBean) context.getBean("timerFactoryBean");
如果你按照上述方式获取该Bean,将抛出如下异常:
Exception in thread "main" java.lang.ClassCastException: net.xz.go.spring.task.TaskTimer cannot be cast to net.xz.go.spring.TimerFactoryBean
at net.xz.go.BootApplication.main(BootApplication.java:29)
也就是直接通过工厂bean的名称获取到的Bean是该工厂生成的Bean,而不是工厂Bean本身,那么我们可以通过如下方式获取工厂Bean本身:
TimerFactoryBean timerFactoryBean = (TimerFactoryBean) context.getBean("&timerFactoryBean");
3.名称转换
//org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
public static String transformedBeanName(String name) {
Assert.notNull(name, "'name' must not be null");
String beanName = name;
//如果Bean名称以“&”开头,则去掉“&”符号
while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
return beanName;
}
这里需要注意一点,缓存指的是单例模式的Bean缓存,因为如果是原型模式,是不能直接从缓存获取的。
1.从缓存中根据名称获取缓存对象
//org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
//该方法只是从以下缓存中获取对象
Object sharedInstance = getSingleton(beanName);
//缓存
/** Cache of singleton objects: bean name --> bean instance */
private final Map singletonObjects = new ConcurrentHashMap<>(256);
/** Cache of singleton factories: bean name --> ObjectFactory */
private final Map> singletonFactories = new HashMap<>(16);
/** Cache of early singleton objects: bean name --> bean instance */
private final Map earlySingletonObjects = new HashMap<>(16);
2.如果缓存对象不为空
//org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// Don't let calling code try to dereference the factory if the bean isn't a factory.
//如果name以“&”开头,则实例对象必须是FactoryBean类型
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
}
// Now we have the bean instance, which may be a normal bean or a FactoryBean.
// If it's a FactoryBean, we use it to create a bean instance, unless the
// caller actually wants a reference to the factory.
//1.如果name以“&”开头,且实例对象确实是FactoryBean类型,直接返回FactoryBean实例,这也是
//为什么我们必须通过“&”获取FactoryBean对象
//2.如果实例对象不是FactoryBean对象直接返回
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
//代码走到这里说明实例对象是FactoryBean类型,但name并非以“&”开头,这使将调用
//FactoryBean.getObject方法返回真正的Bean对象
//这里也符合上面的演示结果,直接通过timerFactoryBean获取到的是TimerTask对象而非
//TimerFactoryBean对象
Object object = null;
if (mbd == null) {
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory.
FactoryBean> factory = (FactoryBean>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
1.如果父类容器存在,先委托父类容器获取Bean
DefaultListableBeanFactory不存在父类容器,不进行分析。
2.从BeanDefinitionMap中获取Bean定义
//org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
//getMergedLocalBeanDefinition是将beanDefinitionMap中的ScannedGenericBeanDefinition转换为
//RootBeanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
3.先初始化当前Bean依赖的其它Bean
//org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
//依次初始化当前Bean锁依赖的类,即当前Bean类的@DependOn注解所指定的类
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);
getBean(dep);
}
}
到现在万事俱备只欠东风,即已经拿到当前Bean定义,以初始化当前Bean所依赖的Bean,现在将要开始真正创建Bean。
这里也单例模式为主介绍
//org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
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);
}
1.如果有缓存实例对象直接返回
2.回调singletonFactory.getObject()方法创建Bean
最终调用的是AbstractAutowireCapableBeanFactory.createBean方法,该方法执行步骤如下
步骤一:从Bean定义中解析出该Bean对应的Class类
//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])
Class> resolvedClass = resolveBeanClass(mbd, beanName);
步骤二:在Bean被实例化(并非初始化)之前给BeanPostProcessor一个机会去生成代理对象,直接返回
注意这里的BeanPostProcessor必须继承自InstantiationAwareBeanPostProcessor,该类不同于BeanPostProcessor接口,其提供了在Bean被实例化之前,根据Class对象构建一个代理类。
//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
//这里将调InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation
//方法,我们可以通过实现该接口,直接在这里生成对象返回。
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
//如果我们已经生成对象,那么依然要给实现BeanPostProcessor接口的类一个机会在Bean
//被实例化且初始化之后,作一些初始化之后的操作
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
这里其实相当于Spring容器给了一个我们自己去实例化Bean的机会,即Spring相当于又做了一次控制反转,而这次是将自己的机会反转给你,你可以创建一个对象或者代理对象。
步骤三:如果我们不利于Spring给我们自己实例化对象的机会,则由Spring容器为我们实例化对象
//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
//Spring容器为我们实例化对象(即控制反转),我们看doCreateBean方法
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
1.创建Bean实例
//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
createBeanInstance方法执行流程如下:
1.从BeanDefinition中解析出Class对象
//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance
Class> beanClass = resolveBeanClass(mbd, beanName);
2.对Class对象进行访问权限判断
//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance
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());
}
3.给开发者机会通过其它手段创建Bean
这里只是提到这种方式,具体如何使用,请自行搜索。
//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance
//在创建BeanDefinition的时候,可以设置回调,通过回调方法创建Bean
Supplier> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
//通过工厂方法创建Bean
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
4.实例化bean
寻找一种实例化策略去生成Bean实例,默认策略为CglibSubclassingInstantiationStrategy,。
//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#instantiateBean
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
//SimpleInstantiationStrategy.java
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
// Don't override the class with CGLIB if no overrides.
//如果没有override方法通过反射实例化对象,否则通过CGLIB创建代理对象
if (!bd.hasMethodOverrides()) {
Constructor> constructorToUse;
synchronized (bd.constructorArgumentLock) {
constructorToUse = (Constructor>) bd.resolvedConstructorOrFactoryMethod;
if (constructorToUse == null) {
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>) clazz::getDeclaredConstructor);
}
else {
constructorToUse = clazz.getDeclaredConstructor();
}
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Throwable ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// Must generate CGLIB subclass.
return instantiateWithMethodInjection(bd, beanName, owner);
}
}
通过上述步骤之后,TimerTask实例已经生成,但是这时时候,其属性task对象依然为空。接下来我们看一下依赖注入的过程。
//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
1.Spring容器首先给了一个我们自己注入属性的机会(例如用set方法)
//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean
//通过实现InstantiationAwareBeanPostProcessor 重写postProcessAfterInstantiation方法,自己注入属性
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
2.Spring容器为我们自动注入依赖属性
当我们跳过第一步时,Spring为我们实行依赖注入。
////org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean
//在前文我们了解到Spring为我们提供了钩子函数,用于在Bean被实例化之后操作Bean,依赖注入就是通过钩子
//函数org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues
//为我们处理依赖注入的属性
if (hasInstAwareBpps) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
所以我们只需要看org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues是如何处理依赖注入的:
//org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
metadata.inject(bean, beanName, pvs);
}
其中InjectionMetadata 描述了当前类需要注入的属性信息,其生成过程如下:
//org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
private InjectionMetadata findAutowiringMetadata(String beanName, Class> clazz, @Nullable PropertyValues pvs) {
// Fall back to class name as cache key, for backwards compatibility with custom callers.
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// Quick check on the concurrent map first, with minimal locking.
//首先判断缓存中有没有当前Bean的依赖注入元数据信息
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
metadata.clear(pvs);
}
//此处解析Bean的Class类真正构造依赖注入元数据信息
metadata = buildAutowiringMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
依赖注入元数据构造过程:
//org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
private InjectionMetadata buildAutowiringMetadata(final Class> clazz) {
LinkedList elements = new LinkedList<>();
Class> targetClass = clazz;
do {
final LinkedList currElements = new LinkedList<>();
//1.获取当前类所有属性
//2.判断属性上是否有@Autowire和@Value属性
//3.获取@Autowire属性的required值
//4.构建一个FiledElement表示当前需要注入的属性
ReflectionUtils.doWithLocalFields(targetClass, field -> {
AnnotationAttributes ann = findAutowiredAnnotation(field);
if (ann != null) {
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isWarnEnabled()) {
logger.warn("Autowired annotation is not supported on static fields: " + field);
}
return;
}
boolean required = determineRequiredStatus(ann);
currElements.add(new AutowiredFieldElement(field, required));
}
});
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
if (Modifier.isStatic(method.getModifiers())) {
if (logger.isWarnEnabled()) {
logger.warn("Autowired annotation is not supported on static methods: " + method);
}
return;
}
if (method.getParameterCount() == 0) {
if (logger.isWarnEnabled()) {
logger.warn("Autowired annotation should only be used on methods with parameters: " +
method);
}
}
boolean required = determineRequiredStatus(ann);
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new AutowiredMethodElement(method, required, pd));
}
});
elements.addAll(0, currElements);
//解析该类的父类是否有需要自动注入的属性
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return new InjectionMetadata(clazz, elements);
}
用上面的TimerTask举例,最终的解析结果如下:
解析完之后,进行依赖注入过程:
//org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues
try {
metadata.inject(bean, beanName, pvs);
}
InjectionMetadata.inject最终调用InjectedElement.inject方法注入每一个属性:
//org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
Object value;
if (this.cached) {
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
else {
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
desc.setContainingClass(bean.getClass());
Set autowiredBeanNames = new LinkedHashSet<>(1);
Assert.state(beanFactory != null, "No BeanFactory available");
TypeConverter typeConverter = beanFactory.getTypeConverter();
try {
//从BeanFactory中获取依赖的对象
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
synchronized (this) {
if (!this.cached) {
if (value != null || this.required) {
this.cachedFieldValue = desc;
registerDependentBeans(beanName, autowiredBeanNames);
if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
if (beanFactory.containsBean(autowiredBeanName)) {
if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
this.cachedFieldValue = new ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
}
}
}
}
else {
this.cachedFieldValue = null;
}
this.cached = true;
}
}
}
if (value != null) {
ReflectionUtils.makeAccessible(field);
//为当前Bean设置依赖的对象
field.set(bean, value);
}
}
通过上述Bean实例化、依赖注入过程,Bean已创建完毕,接下来Spring为我们提供了Bean初始化过程,我们可以在此期间,自定义初始化该Bean或者为该Bean生成代理类。
//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean
//Bean可实现BeanNameAware,BeanClassLoaderAware,BeanFactoryAware接口设置Bean的名称,类加载器
//BeanFactory等
invokeAwareMethods(beanName, bean);
//1.Bean可实现InitializingBean接口,自定义初始化Bean
//2.指定的init-method方法
invokeInitMethods(beanName, wrappedBean, mbd);
//Bean实现BeanPostProcessor接口,自定义初始化Bean
applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName)
本文简述了从getBean内部的执行流程,大概过程如下:
1.从beanDefinitionMap中获取Bean定义BeanDefinition
2.在Spring进行实例化Bean事前,通过钩子类org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation为用户提供自己实例化的机会。
3.如果用户未进行实例化,则Spring根据BeanDefinition通过反射机制实例化Bean。
4.在实例化之后Spring提供钩子函数org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation让用户自己注入依赖属性。
5.如果用户未自己注入依赖属性,则Spring通过钩子函数org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues实行依赖注入过程。
6.依赖注入过程为,获取当前Bean实例的所有属性,判断属性是否含有@Autowired或者@Value属性,如果有则从beanFactory中获取对应的bean,注入到当前bean当中。
7.通过钩子函数InitializingBean和BeanPostProcesssor,在Bean创建之后,对Bean进行自定义初始化操作。
本文只是梳理了大概流程,对于有些知识点并未深入研究,如有不对之处,还请指正。