• Spring 源码学习


    本文作者:geek,一个聪明好学的同事

    1. 简介

    开发中我们常用@Commpont,@Service,@Resource等注解或者配置xml去声明一个类,使其成为spring容器中的bean,以下我将用从源码角度看以AnnotationConfigApplicationContext为例看spring如何把带有注解的类生成spring中bean。

    2. 示例代码

    public class TestContext {
    	public static void main(String[] args) {
    		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
    		SingleBean singleBean = context.getBean(SingleBean.class);
    		System.out.println("<=====>"+singleBean.getTestStr());
    	}
    }
    
    @ComponentScan("com.geek")
    public class AppConfig {
    }
    
    @Component
    public class SingleBean {
    	private String testStr = "testStr";
    
    	public String getTestStr() {
    		return testStr;
    	}
    }
    

    注意:以上代码仅需要引入spring-context依赖即可。

    3. 源码分析

    ​ 上面的demo在调用AnnotationConfigApplicationContext构造函数的时候,AppConfig类会被注册到AnnotatedBeanDefinitionReader,由这个reader把AppConfig解释为beanDefination,从而被spring获取到要实例化的类信息,以下为bean生产的源码及其注释。(源码基于springFramework 5.1.X)

    3.1 创建入口

    ​ 单例bean的创建的入口为DefaultListableBeanFactory.java#preInstantiateSingletons,下面源码可见创建的bean条件为非抽象,非@LazyInit注解,Scope为singleTon(默认为singleTon)。

    @Override
    	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.
    		//所有可能需要去实例化的class(lazy,scope)
    		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
    
    		// Trigger initialization of all non-lazy singleton beans...
    		for (String beanName : beanNames) {
    			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
    			/**
    			 * 非抽象,非懒初始化,单例bean
    			 */
    			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
    				if (isFactoryBean(beanName)) {
    					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
    					if (bean instanceof FactoryBean) {
    						final 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) {
    							getBean(beanName);
    						}
    					}
    				}
    				//非工厂bean实例化
    				else {
    					getBean(beanName);
    				}
    			}
    		}
    		/**
    		 * 实例化完成后触发实现了SmartInitializingSingleton方法的bean
    		 * 的afterSingletonsInstantiated方法
     		 */
    		// Trigger post-initialization callback for all applicable beans...
    		for (String beanName : beanNames) {
    			Object singletonInstance = getSingleton(beanName);
    			if (singletonInstance instanceof SmartInitializingSingleton) {
    				final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
    				if (System.getSecurityManager() != null) {
    					AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
    						smartSingleton.afterSingletonsInstantiated();
    						return null;
    					}, getAccessControlContext());
    				}
    				else {
    					smartSingleton.afterSingletonsInstantiated();
    				}
    			}
    		}
    	}
    
    

    3.2 创建前doGetBean代码逻辑

    getBean方法进来后便是直接调用doGetBean,doGetBean执行的源码解释如下:
    
    protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
    			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
    		/**
    		 * 获取beanName
    		 * 1,去掉factortoryBean前缀&
    		 * 2,带有别名的bean转换为原来名字
    		 */
    		final String beanName = transformedBeanName(name);
    		Object bean;
    		// Eagerly check singleton cache for manually registered singletons.
    		/**
    		 * 从DefaultSingletonBeanRegistry的singletonObjects
    		 * (spring内部用来缓存单例bean的currentHashMap)检查是否存在该bean,不存在则创建
    		 * 涉及单例模式下的循环依赖解决
    		 */
    		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 + "'");
    				}
    			}
    			/**
    			 *获取给定bean实例的对象,如果是Factory Bean,
    			 * 则可以是bean实例本身或其创建的对象。
    			 */
    			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    		}
    		else {
    			// Fail if we're already creating this bean instance:
    			// We're assembly within a circular reference.
    			/**
    			 * 原型模式下的bean存在循环依赖则会抛异常
    			 */
    			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);
    			}
    			try {
    				/**
    				 * 父容器中也找不到该bean,则需要重新实例化
    				 * 1,获取要实例化bean的beanDefinition,
    				 * 2,检查bean的实例化需要依赖的其他bean
    				 */
    				final 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) {
    						/**
    						 * 若给定的依赖 bean 已经注册为依赖给定的bean
    						 */
    						if (isDependent(beanName, dep)) {
    							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    									"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
    						}
    						registerDependentBean(dep, beanName);
    						try {
    							/**
    							 * 递归调用getBean,优先创建依赖的bean
    							 */
    							getBean(dep);
    						}
    						catch (NoSuchBeanDefinitionException ex) {
    							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    									"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
    						}
    					}
    				}
    				// Create bean instance.
    				if (mbd.isSingleton()) {
    					/**
    					 * 通过调用DefaultSingletonBeanRegistry的getSingleton,从而调用核心方法createBean创建
    					 */
    					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);
    				}
    
    				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;
    			}
    		}
    		/**
    		 * 检查需要的bean类型是否符合
    		 */
    		// Check if required type matches the type of the actual bean instance.
    		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;
    	}
    

    doGetBean的操作流程如下:

    1,执行transformedBeanName方法转换beanName

    ​ 传递的参数可能是bean的alias或者为FactoryBean,transformedBeanName执行的操作:(1)若传进来的FactoryBean(FactoryBean以&作为前缀标记),去掉&修饰符。(2)经过(1)的处理后,有alias的bean则从aliasMap中获取bean的原始beanName。

    2,从容器的缓存中获取bean

    ​ getSingleton先从spring三级缓存中的第一级singletonObjects(Map结构)中获取,若不存在,则检查该bean是否正在创建isSingletonCurrentlyInCreation(beanName)) ,正在创建的bean会从二级缓存earlySingletonObjects(Map结构)获取。获取到缓存的bean后会调用AbstractBeanFactory#getObjectForBeanInstance转换bean的实例本身返回。因为从缓存中拿到的可能是factoryBean,所以getObjectForBeanInstance需要把是通过从缓存factoryBeanObjectCache获取或通过factory.getObject()获得相应的bean返回。

    3,bean实例化前检查

    ​ (1)先检查是否原型模式下的bean是否存在循环依赖,是则会抛异常。

    ​ (2)检查父类工厂(parentBeanFactory)是否存在,存在则从parentBeanFactory中递归调用doGetBean。

    ​ (3)获取改bean的beanDefinition,检查该bean实例化过程中是否涉及依赖了其他的bean,若是则递归调用getBean,优先创建依赖的bean。(涉及单例下的循环以来解决,下篇文章详细介绍)。

    ​ (4)对创建bean代码加synchronized和执行beforeSingletonCreation(beanName)前置处理。

    3.3 创建前createBean逻辑

    ​ 经过前面的doGetBean的一轮检查与准备后,便在AbstractAutowireCapableBeanFactory#createBean中开始bean的创建。

    /**
    	 * Central method of this class: creates a bean instance,
    	 * populates the bean instance, applies post-processors, etc.
    	 * 解析指定 BeanDefinition 的 class
    	 * 处理 override 属性
    	 * 实例化的前置处理
    	 * 创建 bean
    	 * @see #doCreateBean
    	 */
    	@Override
    	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;
    
    		// Make sure bean class is actually resolved at this point, and
    		// clone the bean definition in case of a dynamically resolved Class
    		// which cannot be stored in the shared merged bean definition.
    		/**
    		 * 解释bean的class,看beanDefinition是否有class,否则load class
    		 */
    		Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
    		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
    			mbdToUse = new RootBeanDefinition(mbd);
    			mbdToUse.setBeanClass(resolvedClass);
    		}
    		/**
    		 * 对bean不存在lookup-method 和 replace-method
    		 * 标记其方法的overloaded为false
    		 */
    		// Prepare method overrides.
    		try {
    			mbdToUse.prepareMethodOverrides();
    		}
    		catch (BeanDefinitionValidationException ex) {
    			throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
    					beanName, "Validation of method overrides failed", ex);
    		}
    
    		try {
    			/**
    			 * 调用实现实现BeanPostProcessor的bean后置处理生成代理对象,
    			 * 有代理对象则直接返回代理对象
    			 */
    			// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
    			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);
    		}
    	}
    
    

    createBean的操作流程如下:

    1,resolveBeanClass

    ​ 解释beanDefinition的class,并且保存在beanDefinition中。

    2,prepareMethodOverrides

    ​ 处理bean中的lookup-method (在单例bean用 @Lookup注解标记的方法,注解的方法返回的对象是原型)和 replace-method( 标记的方法,标记bean中A的方法被实现被另外一个实现MethodReplacer接口的B方法替代)。

    3,resolveBeforeInstantiation

    ​ 调用实现实现BeanPostProcessor的bean后置处理生成代理对象,有代理对象则直接返回代理对象。(spring AOP则是基于此处实现)

    3.4 bean的真正实例化createBeanInstance

    ​ 在AbstractAutowireCapableBeanFactory#createBeanInstance中,真正创建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回调方法创建
    		 */
    		Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
    		if (instanceSupplier != null) {
    			return obtainFromSupplier(instanceSupplier, beanName);
    		}
    		/**
    		 * 通过工厂方法创建 bean 实例,可以是静态工厂方法或者实例工厂
    		 */
    		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) {
    				/**
    				 * 查找已经bean已经缓存解析的构造函数或者工厂方法
    				 */
    				if (mbd.resolvedConstructorOrFactoryMethod != null) {
    					resolved = true;
    					autowireNecessary = mbd.constructorArgumentsResolved;
    				}
    			}
    		}
    		/**
    		 * 已经有缓存的构造函数或者工厂方法,直接实例化
    		 */
    		if (resolved) {
    			if (autowireNecessary) {
    				return autowireConstructor(beanName, mbd, null, null);
    			}
    			else {
    				return instantiateBean(beanName, mbd);
    			}
    		}
    		/**
    		 * 通过实现BeanPostProcessor的代理类autowired的构造函数实例化
    		 */
    		// 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);
    		}
    		/**
    		 * 通过本身带有autowired的构造函数实例化,通过调用反射newInstance实现
    		 */
    		// Preferred constructors for default construction?
    		ctors = mbd.getPreferredConstructors();
    		if (ctors != null) {
    			return autowireConstructor(beanName, mbd, ctors, null);
    		}
    		/**
    		 * 无参构造函数实例化,通过调用反射newInstance实现
    		 */
    		// No special handling: simply use no-arg constructor.
    		return instantiateBean(beanName, mbd);
    	}
    
    

    由上述源码可以看出,实例化bean操作流程如下:

    1,如果存在 Supplier 回调,则通过提供supplier回调方法创建,如以下方式定义的bean:

    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = Spring5Application.class)
    public class BeanRegistrationTest {
        @Autowired
        private GenericWebApplicationContext context;
        
        context.registerBean(A.class, () -> new A());
    }
    

    2,如果存在工厂方法,则通过工厂方法创建 bean 实例,可以是静态工厂方法或者实例工厂,如以下方式定义的bean:

    public class AFactory implements FactoryBean<A> {
    	@Override
    	public A getObject() throws Exception {
    		return new A();
    	}
    	@Override
    	public Class<?> getObjectType() {
    		return A.class;
    	}
    }
    //或:
    @Configuration
    public class BeanConfigration {
    	@Bean
    	public A a(){
    		return new A();
    	}
    
    }
    

    3,已经有缓存的构造函数或者工厂方法,直接实例化。

    4,以上三点都不存在,则使用带参构造函数与无参构造函数实例化。如以下方式定义的bean:

    @Commponet
    public class A{}
    

    4.总结

    ​ spring单例bean的实例化流程大概就是这样,很多细节地方,包括循环依赖处理,bean属性填充等细节点下一章介绍。

    参考

    查看更多文章关注公众号:好奇心森林
    Wechat

  • 相关阅读:
    在有多个input的表单当中按回车按钮,如何不自动提交表单,而触发某个按钮的事件
    login.jsp
    json数据源
    translation.js
    cookie.js
    i18next.min.js
    struts2拦截器实现原理
    proxy-target-class="true" 与proxy-target-class="false"的区别(声明事务的时候)
    NavLink
    【转载】target='_blank' 安全漏洞示例
  • 原文地址:https://www.cnblogs.com/hackingForest/p/13054173.html
Copyright © 2020-2023  润新知