接着 我们正式开始学习获取 bean 实例方法,该方法是Spring 最核心的方法,也是最难的方法,我们首先不能扣太多的细节,先从一个比较简单的实例化的依赖注入入手。
@Overridepublic Object getBean(String name) throws BeansException {// 获取name对应的bean实例,如果不存在,则创建一个return doGetBean(name, null, null, false);}
doGetBean 方法详解。
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)throws BeansException {// 1.解析beanName,主要是解析别名、去掉FactoryBean的前缀“&”String beanName = transformedBeanName(name);Object bean;// 2.从Spring的三级缓存中获取bean,解决循环依赖的主要的思想// 当A依赖B,B返回来也依赖A的时候,这个时候获取到的A就是从Spring的第三级缓存中获取到Object sharedInstance = getSingleton(beanName);// 6.如果不是仅仅做类型检测,而是创建bean实例,这里要将beanName放到alreadyCreated缓存if (!typeCheckOnly) {markBeanAsCreated(beanName);}try {// 7.根据beanName重新获取MergedBeanDefinition(步骤6将MergedBeanDefinition删除了,这边获取一个新的)RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);checkMergedBeanDefinition(mbd, beanName, args);// 8.拿到当前bean依赖的bean名称集合,在实例化自己之前,需要先实例化自己依赖的beanString[] dependsOn = mbd.getDependsOn();if (dependsOn != null) {// 8.1 遍历当前bean依赖的bean名称集合for (String dep : dependsOn) {// 8.2 检查dep是否依赖于beanName,即检查是否存在循环依赖if (isDependent(beanName, dep)) {// 8.3 如果是循环依赖则抛异常throw new BeanCreationException("Circular depends-on relationship between '" );}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.创建bean实例// scope为singleton的bean创建(新建了一个ObjectFactory,并且重写了getObject方法)if (mbd.isSingleton()) {sharedInstance = getSingleton(beanName, () -> {try {// ****调用createBean创建Bean实例****return createBean(beanName, mbd, args);}});bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}}// 10.检查所需类型是否与实际的bean对象的类型匹配if (requiredType != null && !requiredType.isInstance(bean)) {T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);if (convertedBean == null) {throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());}return convertedBean;}return (T) bean;}
createBean方法总体流程
@Overrideprotected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {RootBeanDefinition mbdToUse = mbd;// 1.解析beanName对应的Bean的类型,例如:com.joonwhee.open.demo.service.impl.UserServiceImplClass<?> resolvedClass = resolveBeanClass(mbd, beanName);if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {// 如果resolvedClass存在,并且mdb的beanClass类型不是Class,并且mdb的beanClass不为空(则代表beanClass存的是Class的name),// 则使用mdb深拷贝一个新的RootBeanDefinition副本,并且将解析的Class赋值给拷贝的RootBeanDefinition副本的beanClass属性,// 该拷贝副本取代mdb用于后续的操作mbdToUse = new RootBeanDefinition(mbd);mbdToUse.setBeanClass(resolvedClass);}try {// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.// 3.实例化前的处理,给InstantiationAwareBeanPostProcessor一个机会返回代理对象来替代真正的bean实例,达到“短路”效果Object bean = resolveBeforeInstantiation(beanName, mbdToUse);// 4.如果bean不为空,则会跳过Spring默认的实例化过程,直接使用返回的beanif (bean != null) {return bean;}}// 5.创建Bean实例(真正创建Bean的方法)Object beanInstance = doCreateBean(beanName, mbdToUse, args);return beanInstance;}
doCreateBean方法
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)throws BeanCreationException {// Instantiate the bean.// 1.新建Bean包装类BeanWrapper instanceWrapper = null;if (mbd.isSingleton()) {// 2.如果是FactoryBean,则需要先移除未完成的FactoryBean实例的缓存// *********重点*********instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);}if (instanceWrapper == null) {// 3.根据beanName、mbd、args,使用对应的策略创建Bean实例,并返回包装类BeanWrapperinstanceWrapper = createBeanInstance(beanName, mbd, args);}// 4.拿到创建好的Bean实例final Object bean = instanceWrapper.getWrappedInstance();// 5.拿到Bean实例的类型Class<?> beanType = instanceWrapper.getWrappedClass();if (beanType != NullBean.class) {mbd.resolvedTargetType = beanType;}// Allow post-processors to modify the merged bean definition.// 6.应用后置处理器MergedBeanDefinitionPostProcessor,允许修改MergedBeanDefinition,// Autowired注解正是通过此方法实现注入类型的预解析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;}}// 7.判断是否需要提早曝光实例:单例 && 允许循环依赖 && 当前bean正在创建中boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&isSingletonCurrentlyInCreation(beanName));if (earlySingletonExposure) {// 8.提前曝光beanName的ObjectFactory,放入到Sprign的三级缓存中addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));}// Initialize the bean instance.初始化bean实例。Object exposedObject = bean;try {// 9.对bean进行属性填充;其中,可能存在依赖于其他bean的属性,则会递归初始化依赖的bean实例populateBean(beanName, mbd, instanceWrapper);exposedObject = initializeBean(beanName, exposedObject, mbd);}//......return exposedObject;}
createBeanInstance创建Bean实例方法
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {// Make sure bean class is actually resolved at this point.// 解析bean的类型信息,Class<?> beanClass = resolveBeanClass(mbd, beanName);// beanClass != null && 当前类不是public && 不允许访问非公共构造函数和方法。抛出异常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());}// 1. 是否有bean的 Supplier 接口,如果有,通过回调来创建beanSupplier<?> instanceSupplier = mbd.getInstanceSupplier();if (instanceSupplier != null) {return obtainFromSupplier(instanceSupplier, beanName);}// 2. 如果工厂方法不为空,则使用工厂方法初始化策略// 通过 @Bean 注解方法注入的bean或者xml 配置factory-method属性注入的// BeanDefinition 会存在这个值。而注入这个bean的方法就是工厂方法。后面会详细解读if (mbd.getFactoryMethodName() != null) {// 执行工厂方法,创建beanreturn instantiateUsingFactoryMethod(beanName, mbd, args);}/* 3. 尝试使用构造函数构建bean,后面详解* 经过上面两步,Spring确定没有其他方式来创建bean,所以打算使用构造函数来进行创建bean。* 但是 bean 的构造函数可能有多个,需要确定使用哪一个。*/// resolved 表示构造函数是否已经解析完成boolean resolved = false;// autowireNecessary: 是否需要自动注入(即是否需要解析构造函数参数)boolean autowireNecessary = false;if (args == null) {// 2.加锁synchronized (mbd.constructorArgumentLock) {// 一个类可能有多个不同的构造函数,每个构造函数参数列表不同,所以调用前需要根据参数锁定对应的构造函数或工程方法// 如果这个bean的构造函数或者工厂方法已经解析过了,会保存到 mbd.resolvedConstructorOrFactoryMethod 中。这里来判断是否已经解析过了。if (mbd.resolvedConstructorOrFactoryMethod != null) {// 2.1 则将resolved标记为已解析resolved = true;// 2.2 根据constructorArgumentsResolved判断是否需要自动注入autowireNecessary = mbd.constructorArgumentsResolved;}}}// 如果已经解析过则使用功能解析好的构造函数方法,不需要再次解析。// 这里的是通过 mbd.resolvedConstructorOrFactoryMethod 属性来缓存解析过的构造函数。if (resolved) {if (autowireNecessary) {// 3.1 需要自动注入,则执行构造函数自动注入return autowireConstructor(beanName, mbd, null, null);} else {// 3.2 否则使用默认的构造函数进行bean的实例化return instantiateBean(beanName, mbd);}}// Spring通过调用后置处理器的determineCandidateConstructors方法将所有被@Autowired标注的构造方法给查找了出来,// 如果不存在缓存则需要进行解析,这里通过 determineConstructorsFromBeanPostProcessors 方法调用了// SmartInstantiationAwareBeanPostProcessor.determineCandidateConstructors 的后处理器方法来进行解析,// Spring 默认的实现在AutowiredAnnotationBeanPostProcessor.determineCandidateConstructors 方法中。// 通过determineCandidateConstructors 方法获取到了候选的构造函数(因为满足条件的构造函数可能不止一个,需要进行进一步的选择)。Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);if (ctors != null ||mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {// 5.如果ctors不为空 || mbd的注入方式为AUTOWIRE_CONSTRUCTOR || mdb定义了构造函数的参数值 || args不为空,则执行构造函数自动注入return autowireConstructor(beanName, mbd, ctors, args);}// No special handling: simply use no-arg constructor.// 6.没有特殊处理,则使用默认的构造函数进行bean的实例化return instantiateBean(beanName, mbd);}
创建实例的方法通常有以下几种:
Supplier方法 : 留给用户可以进行扩展的方法
public class CustomSupplierBeanFactoryPostProcessor implements BeanFactoryPostProcessor {//自己定义了 supplier@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition) beanFactory.getBeanDefinition("student");beanDefinition.setInstanceSupplier(SupplierObject::create);System.out.println("do Custom Supplier BeanFactoryPostProcessor");}// 没有定义 supplier,这样也可以。@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition) beanFactory.getBeanDefinition("student");beanDefinition.setInstanceSupplier(()->{Student custom = new Student();custom.setStudentName("zhao");return custom;});System.out.println("do Custom Supplier BeanFactoryPostProcessor");}}
工厂方法:https://www.cnblogs.com/javastack/p/13431216.html
构造函数自动装配(通常指带有参数的构造函数)
简单实例化
1、通过BeanUtils,它使用了JVM的反射功能来生成Java对象实例
2、用CGLIB来生成,CGLIB是一种常用的字节码生成器的类库
@Overridepublic Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {// Don't override the class with CGLIB if no overrides.// 如果MethOverrides为空.// spring有两个标签参数会产生MethodOverrides ,分别是 lookup-method,replaced-method// 其中replaced-method使用方法 https://blog.csdn.net/wang0907/article/details/114325252if (bd.getMethodOverrides().isEmpty()) {Constructor<?> constructorToUse;synchronized (bd.constructorArgumentLock) {// 获取bd.resolvedConstructorOrFactoryMethod已解析的构造器或工厂方法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 {else {//通过bean的类clazz来得到声明的构造函数constructorToUse = clazz.getDeclaredConstructor((Class[]) null);}// 并赋值回给bd.resolvedConstructorOrFactoryMethodbd.resolvedConstructorOrFactoryMethod = constructorToUse;}catch (Throwable ex) {throw new BeanInstantiationException(clazz, "No default constructor found", ex);}}}// 通过BeanUtils方法实例化beanreturn BeanUtils.instantiateClass(constructorToUse);}else {// Must generate CGLIB subclass.// 如果MethodOverrides不为空,生成cglib的子类return instantiateWithMethodInjection(bd, beanName, owner);}}
