基于注解的IoC容器

最后都变了- 提交于 2021-02-18 21:21:52

BeanFactory

  • SpringBean的创建是典型的工厂模式,这一系列的Bean工厂,即IoC容器为开发者管理了Bean之间的依赖关系。BeanFactory作为最顶层的一个接口类,定义了IoC容器的基本规范。
  • 在BeanFactory里只对IoC容器的基本行为做了定义,不关心Bean是如何定义及怎样加载的。正如我们只关心能从工厂中获取到什么产品,不关心工厂是怎么生产这些产品的
public interface BeanFactory {
    //对FactoryBean的转义定义,如果使用Bean的名字检索FactoryBean得到的对象是工厂生成的对象,如果需要得到工厂本身,需要转义
    String FACTORY_BEAN_PREFIX = "&";
    //根据Bean的名字获取IoC中Bean的实例
    Object getBean(String var1) throws BeansException;
    //根据Bean的名字和Class类型获取Bean的实例,增强了类型安全验证机制
    <T> T getBean(String var1, Class<T> var2) throws BeansException;
    
    Object getBean(String var1, Object... var2) throws BeansException;

    <T> T getBean(Class<T> var1) throws BeansException;

    <T> T getBean(Class<T> var1, Object... var2) throws BeansException;

    <T> ObjectProvider<T> getBeanProvider(Class<T> var1);

    <T> ObjectProvider<T> getBeanProvider(ResolvableType var1);
    
    boolean containsBean(String var1);

    boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;

    boolean isPrototype(String var1) throws NoSuchBeanDefinitionException;

    boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException;

    boolean isTypeMatch(String var1, Class<?> var2) throws NoSuchBeanDefinitionException;

    @Nullable
    Class<?> getType(String var1) throws NoSuchBeanDefinitionException;

    //得到Bean实例的Class对象
    @Nullable
    Class<?> getType(String var1, boolean var2) throws NoSuchBeanDefinitionException;

    String[] getAliases(String var1);
}

注解的发展

  • 在Spring2.0及以后的版本中,引入了基于注解(Annotation)方式的配置,注解(Annotation)是JDK1.5引入的一个新特性。用户简化Bean的配置,可以取代XML配置文件
Spring IoC容器对于类级别的注解和类内部的注解处理策略如下:
  • 类级别的注解: @Component,@Respository,@Service等,Spring IoC容器根据注解的过滤规则扫描读取注解Bean定义类,并将其注册到IoC容器中。
  • 类内部的注解: @Autowire,@Resource等,Spring IoC容器通过Bean后置处理器解析Bean内部的注解

定位Bean扫描路径

  • 在Spring管理注解的Bean定义的容器有两个AnnotationConfigApplicationContext和AnnotationConfigWebApplicationContext,这两个是专门处理Spring注解方式的配置的容器,直接依赖于将注解作为容器配置信息来源的IoC容器。AnnotationConfigWebApplicationContext是AnnotationConfigApplicationContext的Web版本
AnnotationConfigApplicationContext
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {

    //保存一个读取注解的Bean定义读取器,并将其设置到容器中
	private final AnnotatedBeanDefinitionReader reader;

    //保存一个扫描制定类路径中注解Bean定义读取器,并将其设置到容器中
	private final ClassPathBeanDefinitionScanner scanner;


	/**
	 * 默认构造函数,初始化一个空容器,容器中不包含任何Bean信息,需要稍后通过调用其register()
	 * 方法注册配置类,并调用refresh()方法刷新容器,出发容器对注解Bean的载入,解析和注册
	 * Create a new AnnotationConfigApplicationContext that needs to be populated
	 * through {@link #register} calls and then manually {@linkplain #refresh refreshed}.
	 */
	public AnnotationConfigApplicationContext() {
		this.reader = new AnnotatedBeanDefinitionReader(this);
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}

	/**
	 * Create a new AnnotationConfigApplicationContext with the given DefaultListableBeanFactory.
	 * @param beanFactory the DefaultListableBeanFactory instance to use for this context
	 */
	public AnnotationConfigApplicationContext(DefaultListableBeanFactory beanFactory) {
		super(beanFactory);
		this.reader = new AnnotatedBeanDefinitionReader(this);
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}

	/**
	 * 最常用的构造函数,通过将涉及的配置类传递给构造函数,实现将相应的配置类中的Bean自动注册到容器中
	 * Create a new AnnotationConfigApplicationContext, deriving bean definitions
	 * from the given component classes and automatically refreshing the context.
	 * 创建一个新的容器,从给定的组件类派生bean定义,并自动刷新上下文。
	 * @param componentClasses one or more component classes &mdash; for example,
	 * {@link Configuration @Configuration} classes
	 */
	public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
		this();
		register(componentClasses);
		refresh();
	}

	/**
	 * 创建一个新的AnnotationConfigApplicationContext,扫描给定包中的组件,为这些组件注册bean定义,并自动刷新上下文。
	 * Create a new AnnotationConfigApplicationContext, scanning for components
	 * in the given packages, registering bean definitions for those components,
	 * and automatically refreshing the context.
	 * @param basePackages the packages to scan for component classes
	 */
	public AnnotationConfigApplicationContext(String... basePackages) {
		this();
		scan(basePackages);
		refresh();
	}


	/**
	 * Propagate the given custom {@code Environment} to the underlying
	 * {@link AnnotatedBeanDefinitionReader} and {@link ClassPathBeanDefinitionScanner}.
	 */
	@Override
	public void setEnvironment(ConfigurableEnvironment environment) {
		super.setEnvironment(environment);
		this.reader.setEnvironment(environment);
		this.scanner.setEnvironment(environment);
	}

	/**
	 * Provide a custom {@link BeanNameGenerator} for use with {@link AnnotatedBeanDefinitionReader}
	 * and/or {@link ClassPathBeanDefinitionScanner}, if any.
	 * <p>Default is {@link AnnotationBeanNameGenerator}.
	 * <p>Any call to this method must occur prior to calls to {@link #register(Class...)}
	 * and/or {@link #scan(String...)}.
	 * @see AnnotatedBeanDefinitionReader#setBeanNameGenerator
	 * @see ClassPathBeanDefinitionScanner#setBeanNameGenerator
	 * @see AnnotationBeanNameGenerator
	 * @see FullyQualifiedAnnotationBeanNameGenerator
	 */
	public void setBeanNameGenerator(BeanNameGenerator beanNameGenerator) {
		this.reader.setBeanNameGenerator(beanNameGenerator);
		this.scanner.setBeanNameGenerator(beanNameGenerator);
		getBeanFactory().registerSingleton(
				AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, beanNameGenerator);
	}

	/**
	 * Set the {@link ScopeMetadataResolver} to use for registered component classes.
	 * <p>The default is an {@link AnnotationScopeMetadataResolver}.
	 * <p>Any call to this method must occur prior to calls to {@link #register(Class...)}
	 * and/or {@link #scan(String...)}.
	 */
	public void setScopeMetadataResolver(ScopeMetadataResolver scopeMetadataResolver) {
		this.reader.setScopeMetadataResolver(scopeMetadataResolver);
		this.scanner.setScopeMetadataResolver(scopeMetadataResolver);
	}


	//---------------------------------------------------------------------
	// Implementation of AnnotationConfigRegistry
	//---------------------------------------------------------------------

	/**
	 * 为容器注册一个要被处理的注解Bean,新注册的Bean,必须手动调用容器的refreash()方法刷新容器,出发容器对新注册的Bean的处理
	 * Register one or more component classes to be processed.
	 * <p>Note that {@link #refresh()} must be called in order for the context
	 * to fully process the new classes.
	 * @param componentClasses one or more component classes &mdash; for example,
	 * {@link Configuration @Configuration} classes
	 * @see #scan(String...)
	 * @see #refresh()
	 */
	@Override
	public void register(Class<?>... componentClasses) {
		Assert.notEmpty(componentClasses, "At least one component class must be specified");
		this.reader.register(componentClasses);
	}

	/**
	 * Perform a scan within the specified base packages.
	 * <p>Note that {@link #refresh()} must be called in order for the context
	 * to fully process the new classes.
	 * @param basePackages the packages to scan for component classes
	 * @see #register(Class...)
	 * @see #refresh()
	 */
	@Override
	public void scan(String... basePackages) {
		Assert.notEmpty(basePackages, "At least one base package must be specified");
		this.scanner.scan(basePackages);
	}


	//---------------------------------------------------------------------
	// Adapt superclass registerBean calls to AnnotatedBeanDefinitionReader
	//---------------------------------------------------------------------

	@Override
	public <T> void registerBean(@Nullable String beanName, Class<T> beanClass,
			@Nullable Supplier<T> supplier, BeanDefinitionCustomizer... customizers) {

		this.reader.registerBean(beanClass, beanName, supplier, customizers);
	}

}
通过上面的源码可以看出Spring对注解的处理分为以下两种方式
  • 直接将注解Bean注册到容器中:可以在容器初始化时注册;也可以在容器创建之后手动调用注册方法向容器注册,然后通过手动刷新容器对注册的注解Bean进行处理。
  • 通过扫描制定的包及其子包下的所有类处理:在初始化时指定要扫描的路径
refresh()
  • refresh()方法是一个模版方法,规定了IoC容器的启动流程。
public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// 容器准备刷新的方法,获取容器的当前时间,同时给容器设置同步时间
			prepareRefresh();

			// 告诉子类启动refreshBeanFactory()方法,Bean定义资源文件的载入从子类的refreshBeanFactory()方法启动
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// 为BeanFactory配置容器特性,例如类加载器,时间处理器
			prepareBeanFactory(beanFactory);

			try {
				// 为容器的某些子类制定特殊的Post事件处理器
				postProcessBeanFactory(beanFactory);

				// 调用所有注册的BeanFactoryPostProcessor的Bean
				invokeBeanFactoryPostProcessors(beanFactory);

				// 实例化并注册所有BeanPostProcessor Bean,必须在实例化应用Bean之前被调用。
				registerBeanPostProcessors(beanFactory);

				// 初始化MessageSource(信息源,和国际化相关)。如果在此上下文中没有定义,则使用父代的。
				initMessageSource();

				// 初始化容器事件传播器
				initApplicationEventMulticaster();

				// 模板方法,它可以被重载以添加特定上下文的刷新工作。在初始化特殊bean时调用,在实例化单例之前
				onRefresh();

				// 将实现ApplicationListener的bean添加为监听器
				registerListeners();

				// 完成这个上下文的bean工厂的初始化,初始化所有剩余的单例bean
				finishBeanFactoryInitialization(beanFactory);

				// 完成该上下文的刷新,发布容器的生命周期事件
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// 用于销毁该上下文管理的所有Bean的模板方法。默认的实现是销毁上下文中所有缓存的单子,调用DisposableBean.destroy()和/或指定的 "destroy-method"。
可以被重载,在标准单例销毁之前或之后添加特定上下文的Bean销毁步骤,而上下文的BeanFactory仍然处于活动状态。
				destroyBeans();

				// 取消此上下文的刷新尝试,在抛出异常后重置活动标志。
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				// 重置Spring常用的反射元数据缓存
				resetCommonCaches();
			}
		}
	}

FactoryBean和BeanFactory

Beanfactory
  • Bean 工厂,是Spring IoC容器的最高顶层接口就是BeanFactory,它的作用是管理Bean,即实例化,定位,配置应用程序中的对象及建立这些对象之间的依赖
FactoryBean
  • 是一个Bean,作用是产生其他Bean实例。这种Bean实例没有什么特别的要求,仅需要提供一个工厂方法,该方法用来返回其他的Bean实例。通常情况下,Bean无需自己实现工厂模式,Spring容器担任工厂角色
当用户使用容器时,可以使用转义字符“&”来获取FactoryBean本身,以区别通过FactoryBean产生的实例对象和FactoryBean对象本身。

autowiring

Spring IoC容器提供了两种管理Bean依赖关系的方式
  • 显示管理: 通过BeanDefinition的属性值和构造方法实现Bean依赖关系管理
  • autowring: Spring IoC容器有依赖自动配置功能,不需要对Bean属性的依赖关系做显示的生命,只需要配置好autoing属性,IoC容器会自动使用反射的类型和名称,然后基于属性的类型或者名称来自动匹配容器中的Bean,从而完成依赖注入
流程
  • (1)对Bean的属性调用getBean()方法,完成依赖Bean的初始化和依赖注入
  • (2)将依赖Bean的属性引用设置到Bean依赖的Bean属性上
  • (3)将依赖Bean的名称和被依赖Bean的名称存储在IoC容器的集合中

自动装配之依赖注入

依赖注入发生的时间
  • 当Spring IoC容器完成了Bean定义资源的定位,载入和解析注册,IoC容器就可以管理Bean定义的相关数据了,但是此时IoC容器还没有对Bean进行依赖注入(DI),依赖注入发生在以下两种情况:
  • (1) 用户第一次调用getBean()方法时,IoC容器触发依赖注入
  • (2) 当用户在配置文件中将<bean>元素配置了lazy-init=false 属性时,即让容器在解析注册Bean定义时进行预实例化,触发依赖注入
寻找获取bean的入口
  • 在Spring中如果Bean定义为单例模式,则容器在创建之前先从缓存中查找,以确保容器中只有一个实例对象。如果Bean定义为原型模式,则容器每次会创建一个新的实例对象,
  • 具体的Bean实例对象的创建过程由实现了ObjectFactory接口的匿名内部类的createBean()方法完成,ObjectFactory接口使用委派模式,具体的Bean实例创建过程由其实现类AbstractAutowireCapableBeanFactory完成
创建实例对象的源码分析

    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

        // 判断需要创建的Bean是否可以实例化,即是否通过当前类加载器加载
        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 {
            //如果Bean配置了初始化前和初始化后的处理器,则试图返回一个需要创建Bean的代理对象
            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 {
            //创建Bean的入口
            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);
        }
    }
真正创建Bean的方法
    protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
        }

        //封装被创建的Bean对象
        if (instanceWrapper == null) {
            instanceWrapper = this.createBeanInstance(beanName, mbd, args);
        }

        Object bean = instanceWrapper.getWrappedInstance();

        //获取实例化对象的类型
        Class<?> beanType = instanceWrapper.getWrappedClass();
        if (beanType != NullBean.class) {
            mbd.resolvedTargetType = beanType;
        }

        //调用PostProcessor后置处理器
        synchronized(mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                    this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                } catch (Throwable var17) {
                    throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", var17);
                }

                mbd.postProcessed = true;
            }
        }

        //向容器中缓存单例模式的Bean对象,以防止循环依赖
        boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
        if (earlySingletonExposure) {
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
            }

            //这里是一个匿名内部类,为了防止循环引用,尽早持有对象的引用
            this.addSingletonFactory(beanName, () -> {
                return this.getEarlyBeanReference(beanName, mbd, bean);
            });
        }

        //Bean对象的初始化,依赖注入再次触发,这个exposedObject对象在初始化完成之后返回依赖注入的Bean
        Object exposedObject = bean;
        try {

            //将Bean实例对象封装,并且将Bean定义中配置的属性值赋值给实例对象
            this.populateBean(beanName, mbd, instanceWrapper);
            
            //初始化Bean对象
            exposedObject = this.initializeBean(beanName, exposedObject, mbd);
        } catch (Throwable var18) {
            if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
                throw (BeanCreationException)var18;
            }

            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
        }

        if (earlySingletonExposure) {

            // 获取指定名称的已注册的单例模式的Bean对象
            Object earlySingletonReference = this.getSingleton(beanName, false);
            if (earlySingletonReference != null) {
                if (exposedObject == bean) {

                //根据名称获取的已注册的Bean和正在实例化的Bean是同一个则当前实例化的Bean初始化完成
                exposedObject = earlySingletonReference;

                //当前Bean依赖其他Bean,并且当发生循环依赖的时候不允许创建新的实例对象
                else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                    String[] dependentBeans = getDependentBeans(beanName);
                    Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);

                    //获取当前Bean依赖的其他Bean
                    for (String dependentBean : dependentBeans) {

                         //对依赖的Bean进行类型检查
                        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 " +
                                "'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
                    }

            }
        }

        //注册完成依赖注入的Bean
        try {
            this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
            return exposedObject;
        } catch (BeanDefinitionValidationException var16) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);
        }
    }
通过源码注释可以发现,具体的依赖注入在以下的两个方法中
  • (1) createBeanInstance(),生成Bean所包含的Java对象实例
  • (2) populateBean(),对Bean属性的依赖注入进行处理
选择Bean实例化策略
  • 在createBeanInstance()方法中,根据指定的初始化策略,使用简单工厂,工厂方法或者容器的自动装配特性生成java实例对象
//创建Bean的实例对象
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
       
        // 确认Bean是可实例化的
        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) {

                //配置了自动装配属性,使用容器的自动装配进行实例化,容器的自动装配根据参数类型匹配Bean的构造方法
                return autowireConstructor(beanName, mbd, null, null);
            }
            else {

                //使用默认的无参构造进行初始化
                return instantiateBean(beanName, mbd);
            }
        }

        // 使用Bean的构造方法进行初始化
        Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
        if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
                mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
            
            //使用容器的自动装配特性,调用匹配的构造方法进行实例化
            return autowireConstructor(beanName, mbd, ctors, args);
        }

        //使用默认的无参构造方法进行实例化
        return instantiateBean(beanName, mbd);
    }
    
    
    
    
    
//使用默认的无参数构造方法实例化Bean对象
protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
        try {
            Object beanInstance;

            //获取系统的安全管理接口,JDK标准的安全管理API
            if (System.getSecurityManager() != null) {

                //这里是一个匿名内部类,根据实例化策略创建实例对象
                beanInstance = AccessController.doPrivileged(
                        (PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(mbd, beanName, this),
                        getAccessControlContext());
            }
            else {

                //将实例化的对象封装起来
                beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
            }
            BeanWrapper bw = new BeanWrapperImpl(beanInstance);
            initBeanWrapper(bw);
            return bw;
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
        }
    }
  • 从上面的代码可以看出,对使用工厂方法和自动装备特性的Bean,调用相应的工厂方法或参数匹配的构造方法即可完成实例化对象的工作,但是最常使用的默认无参构造方法就需要使用相应的初始化策略(JDK的反射机制或CGLIB)来进行初始化,在getInstantiationStrategy().instantiate()中完成了初始化
执行Bean初始化
  • 在使用默认的五参数构造方法创建Bean的实例化对象时,getInstantiationStrategy().instantiate()方法调用了SimpleInstantiationStrategy类中的实例化Bean的方法

    	@Override
    	public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
    		//如果Bean定义中没有方法覆盖,就不需要CGLIB父类中的方法
    		if (!bd.hasMethodOverrides()) {
    			Constructor<?> constructorToUse;
    			synchronized (bd.constructorArgumentLock) {
    
    			    //获取对象的构造方法或者工厂方法
    				constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
    
                    // 如果没有构造方法或者工厂方法
    				if (constructorToUse == null) {
    
    				    //使用JDK的放射机制
    					final Class<?> clazz = bd.getBeanClass();
    					//判断要实例化的Bean是否是接口
    					if (clazz.isInterface()) {
    						throw new BeanInstantiationException(clazz, "Specified class is an interface");
    					}
    					try {
    						if (System.getSecurityManager() != null) {
    
                                //这里是一个匿名内部类,使用反射机制获取Bean的构造方法
    							constructorToUse = AccessController.doPrivileged(
    									(PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
    						}
    						else {
    							constructorToUse = clazz.getDeclaredConstructor();
    						}
    						bd.resolvedConstructorOrFactoryMethod = constructorToUse;
    					}
    					catch (Throwable ex) {
    						throw new BeanInstantiationException(clazz, "No default constructor found", ex);
    					}
    				}
    			}
    
    			//使用BeanUtils进行实例化,通过反射机制调用其构造方法进行实例化
    			return BeanUtils.instantiateClass(constructorToUse);
    		}
    		else {
    			// 使用CGlib进行实例化
    			return instantiateWithMethodInjection(bd, beanName, owner);
    		}
    	}
    
    instantiateWithMethodInjection()方法调用SimpleInstantiationStrategy的子类CglibSubclassingInstantiationStrategy通过CGLIB来进行初始化,其源码如下:
    	public Object instantiate(@Nullable Constructor<?> ctor, @Nullable Object... args) {
    
                //创建代理子类
    			Class<?> subclass = createEnhancedSubclass(this.beanDefinition);
    			Object instance;
    			if (ctor == null) {
    				instance = BeanUtils.instantiateClass(subclass);
    			}
    			else {
    				try {
    					Constructor<?> enhancedSubclassConstructor = subclass.getConstructor(ctor.getParameterTypes());
    					instance = enhancedSubclassConstructor.newInstance(args);
    				}
    				catch (Exception ex) {
    					throw new BeanInstantiationException(this.beanDefinition.getBeanClass(),
    							"Failed to invoke constructor for CGLIB enhanced subclass [" + subclass.getName() + "]", ex);
    				}
    			}
    			// SPR-10785: set callbacks directly on the instance instead of in the
    			// enhanced class (via the Enhancer) in order to avoid memory leaks.
    			Factory factory = (Factory) instance;
    			factory.setCallbacks(new Callback[] {NoOp.INSTANCE,
    					new LookupOverrideMethodInterceptor(this.beanDefinition, this.owner),
    					new ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)});
    			return instance;
    		}
    
    		/**
    		 * 使用CGLIB为提供的bean定义创建bean类的增强子类。
    		 */
    		private Class<?> createEnhancedSubclass(RootBeanDefinition beanDefinition) {
    
    		    //CGLIB中的类
    			Enhancer enhancer = new Enhancer();
    
    			//将Bean本身作为基类
    			enhancer.setSuperclass(beanDefinition.getBeanClass());
    			enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
    			if (this.owner instanceof ConfigurableBeanFactory) {
    				ClassLoader cl = ((ConfigurableBeanFactory) this.owner).getBeanClassLoader();
    				enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(cl));
    			}
    			enhancer.setCallbackFilter(new MethodOverrideCallbackFilter(beanDefinition));
    			enhancer.setCallbackTypes(CALLBACK_TYPES);
    
    			//使用CGLib的createClass方法生成实例类
    			return enhancer.createClass();
    		}
    	}
    
    CGLiB是一个常用的字节码生成器的类库,它提供了一系列API实现Java字节码的生成和转换功能

    准备依赖注入

    • 前面已经了解到Bean的依赖注入主要分为两个步骤,首先调用createBeanInstance()方法生成Bean所包含的Java对象,然后调用populateBean()方法对Bean属性的依赖注入进行处理。populateBean()方法源码如下:

      //将Bean属性设置到生成的实例对象上
      protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
      		if (bw == null) {
      			if (mbd.hasPropertyValues()) {
      				throw new BeanCreationException(
      						mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
      			}
      			else {
      				// Skip property population phase for null instance.
      				return;
      			}
      		}
      
      		// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
      		// state of the bean before properties are set. This can be used, for example,
      		// to support styles of field injection.
      		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
      			for (BeanPostProcessor bp : getBeanPostProcessors()) {
      				if (bp instanceof InstantiationAwareBeanPostProcessor) {
      					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
      					if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
      						return;
      					}
      				}
      			}
      		}
      
      
      		//获取容器在解析Bean定义资源是为Beandefination设置的属性值
      		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
      
      		int resolvedAutowireMode = mbd.getResolvedAutowireMode();
      		if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
      			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
      			// Add property values based on autowire by name if applicable.
      			if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
      				autowireByName(beanName, mbd, bw, newPvs);
      			}
      			// Add property values based on autowire by type if applicable.
      			if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
      				autowireByType(beanName, mbd, bw, newPvs);
      			}
      			pvs = newPvs;
      		}
      
      		boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
      		boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
      
      		if (hasInstAwareBpps || needsDepCheck) {
      			if (pvs == null) {
      				pvs = mbd.getPropertyValues();
      			}
      			PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
      			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;
      						}
      					}
      				}
      			}
      			if (needsDepCheck) {
      				checkDependencies(beanName, mbd, filteredPds, pvs);
      			}
      		}
      
      		if (pvs != null) {
      
      		    //对属性值进行注入
      			applyPropertyValues(beanName, mbd, bw, pvs);
      		}
      	}
      
      
      
      
      
      
        //解析并注入依赖属性个过程
      	protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
      		if (pvs.isEmpty()) {
      			return;
      		}
      
      		if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {
      			((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
      		}
      
      		//封装属性值
      		MutablePropertyValues mpvs = null;
      		List<PropertyValue> original;
      
      		if (pvs instanceof MutablePropertyValues) {
      			mpvs = (MutablePropertyValues) pvs;
      			if (mpvs.isConverted()) {
      				// Shortcut: use the pre-converted values as-is.
      				try {
      
      				    //设置上下文
      					bw.setPropertyValues(mpvs);
      					return;
      				}
      				catch (BeansException ex) {
      					throw new BeanCreationException(
      							mbd.getResourceDescription(), beanName, "Error setting property values", ex);
      				}
      			}
      			original = mpvs.getPropertyValueList();
      		}
      		else {
      			original = Arrays.asList(pvs.getPropertyValues());
      		}
      
      		TypeConverter converter = getCustomTypeConverter();
      		if (converter == null) {
      			converter = bw;
      		}
      		BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);
      
      		// Create a deep copy, resolving any references for values.
      		List<PropertyValue> deepCopy = new ArrayList<>(original.size());
      		boolean resolveNecessary = false;
      		for (PropertyValue pv : original) {
      			if (pv.isConverted()) {
      				deepCopy.add(pv);
      			}
      			else {
      				String propertyName = pv.getName();
      				Object originalValue = pv.getValue();
      				Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
      				Object convertedValue = resolvedValue;
      				boolean convertible = bw.isWritableProperty(propertyName) &&
      						!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
      				if (convertible) {
      					convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
      				}
      				// Possibly store converted value in merged bean definition,
      				// in order to avoid re-conversion for every created bean instance.
      				if (resolvedValue == originalValue) {
      					if (convertible) {
      						pv.setConvertedValue(convertedValue);
      					}
      					deepCopy.add(pv);
      				}
      				else if (convertible && originalValue instanceof TypedStringValue &&
      						!((TypedStringValue) originalValue).isDynamic() &&
      						!(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
      					pv.setConvertedValue(convertedValue);
      					deepCopy.add(pv);
      				}
      				else {
      					resolveNecessary = true;
      					deepCopy.add(new PropertyValue(pv, convertedValue));
      				}
      			}
      		}
      		if (mpvs != null && !resolveNecessary) {
      			mpvs.setConverted();
      		}
      
      		// Set our (possibly massaged) deep copy.
      		try {
      			bw.setPropertyValues(new MutablePropertyValues(deepCopy));
      		}
      		catch (BeansException ex) {
      			throw new BeanCreationException(
      					mbd.getResourceDescription(), beanName, "Error setting property values", ex);
      		}
      	}
      
      
      
      注入赋值
      //实现属性依赖注入功能
      protected void setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv) throws BeansException {
      		if (tokens.keys != null) {
      			processKeyedProperty(tokens, pv);
      		}
      		else {
      			processLocalProperty(tokens, pv);
      		}
      	}
      
      
      	@SuppressWarnings("unchecked")
      	private void processKeyedProperty(PropertyTokenHolder tokens, PropertyValue pv) {
      		Object propValue = getPropertyHoldingValue(tokens);
      		PropertyHandler ph = getLocalPropertyHandler(tokens.actualName);
      		if (ph == null) {
      			throw new InvalidPropertyException(
      					getRootClass(), this.nestedPath + tokens.actualName, "No property handler found");
      		}
      		Assert.state(tokens.keys != null, "No token keys");
      		String lastKey = tokens.keys[tokens.keys.length - 1];
      
      		if (propValue.getClass().isArray()) {
      			Class<?> requiredType = propValue.getClass().getComponentType();
      			int arrayIndex = Integer.parseInt(lastKey);
      			Object oldValue = null;
      			try {
      				if (isExtractOldValueForEditor() && arrayIndex < Array.getLength(propValue)) {
      					oldValue = Array.get(propValue, arrayIndex);
      				}
      				Object convertedValue = convertIfNecessary(tokens.canonicalName, oldValue, pv.getValue(),
      						requiredType, ph.nested(tokens.keys.length));
      				int length = Array.getLength(propValue);
      				if (arrayIndex >= length && arrayIndex < this.autoGrowCollectionLimit) {
      					Class<?> componentType = propValue.getClass().getComponentType();
      					Object newArray = Array.newInstance(componentType, arrayIndex + 1);
      					System.arraycopy(propValue, 0, newArray, 0, length);
      					setPropertyValue(tokens.actualName, newArray);
      					propValue = getPropertyValue(tokens.actualName);
      				}
      				Array.set(propValue, arrayIndex, convertedValue);
      			}
      			catch (IndexOutOfBoundsException ex) {
      				throw new InvalidPropertyException(getRootClass(), this.nestedPath + tokens.canonicalName,
      						"Invalid array index in property path '" + tokens.canonicalName + "'", ex);
      			}
      		}
      
      		else if (propValue instanceof List) {
      			Class<?> requiredType = ph.getCollectionType(tokens.keys.length);
      			List<Object> list = (List<Object>) propValue;
      			int index = Integer.parseInt(lastKey);
      			Object oldValue = null;
      			if (isExtractOldValueForEditor() && index < list.size()) {
      				oldValue = list.get(index);
      			}
      			Object convertedValue = convertIfNecessary(tokens.canonicalName, oldValue, pv.getValue(),
      					requiredType, ph.nested(tokens.keys.length));
      			int size = list.size();
      			if (index >= size && index < this.autoGrowCollectionLimit) {
      				for (int i = size; i < index; i++) {
      					try {
      						list.add(null);
      					}
      					catch (NullPointerException ex) {
      						throw new InvalidPropertyException(getRootClass(), this.nestedPath + tokens.canonicalName,
      								"Cannot set element with index " + index + " in List of size " +
      								size + ", accessed using property path '" + tokens.canonicalName +
      								"': List does not support filling up gaps with null elements");
      					}
      				}
      				list.add(convertedValue);
      			}
      			else {
      				try {
      					list.set(index, convertedValue);
      				}
      				catch (IndexOutOfBoundsException ex) {
      					throw new InvalidPropertyException(getRootClass(), this.nestedPath + tokens.canonicalName,
      							"Invalid list index in property path '" + tokens.canonicalName + "'", ex);
      				}
      			}
      		}
      
      		else if (propValue instanceof Map) {
      			Class<?> mapKeyType = ph.getMapKeyType(tokens.keys.length);
      			Class<?> mapValueType = ph.getMapValueType(tokens.keys.length);
      			Map<Object, Object> map = (Map<Object, Object>) propValue;
      			// IMPORTANT: Do not pass full property name in here - property editors
      			// must not kick in for map keys but rather only for map values.
      			TypeDescriptor typeDescriptor = TypeDescriptor.valueOf(mapKeyType);
      			Object convertedMapKey = convertIfNecessary(null, null, lastKey, mapKeyType, typeDescriptor);
      			Object oldValue = null;
      			if (isExtractOldValueForEditor()) {
      				oldValue = map.get(convertedMapKey);
      			}
      			// Pass full property name and old value in here, since we want full
      			// conversion ability for map values.
      			Object convertedMapValue = convertIfNecessary(tokens.canonicalName, oldValue, pv.getValue(),
      					mapValueType, ph.nested(tokens.keys.length));
      			map.put(convertedMapKey, convertedMapValue);
      		}
      
      		else {
      			throw new InvalidPropertyException(getRootClass(), this.nestedPath + tokens.canonicalName,
      					"Property referenced in indexed property path '" + tokens.canonicalName +
      					"' is neither an array nor a List nor a Map; returned value was [" + propValue + "]");
      		}
      	}
      
    注入方式小结

    (1) 对于集合类型的属性,将属性值解析为目标类型的集合后直接位置给属性

    (2). 对于非集合类型的属性,大量使用JDK的反射机制,通过属性的getter()方法获取指定属性注入前的值,同时调用属性的setter()方法为属性设置注入后的值

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!