1. 程式人生 > >Spring的IOC的原始碼解析(三)

Spring的IOC的原始碼解析(三)

在《Spring的IOC的原始碼解析(二)》中完成了BFPP和BPP的處理分析;這篇接著分bean的例項化。在用bean工廠建立bean物件時,呼叫的是父類AbstractBeanFactory中提供的getBean的系列方法。往下,在AbstractAutowireCapableBeanFactory的createBean方法中,有下邊一段程式碼,try {    // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.    Object bean = resolveBeforeInstantiation(beanName, mbdToUse);//看分析(1)    if (bean != null) {
        return bean;    }}catch (Throwable ex) {    throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,            "BeanPostProcessor before instantiation of bean failed", ex);}try {    Object beanInstance = doCreateBean(beanName, mbdToUse, args);//生成例項,看分析(2)    if (logger.isDebugEnabled()) {
        logger.debug("Finished creating instance of bean '" + beanName + "'");    }    return beanInstance;}(1) 繼續看resolveBeforeInstantiation方法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()) {//!mbd.isSynthetic()預設是true,如果註冊了InstantiationAwareBeanPostProcessors型別的BPP,右側表示式也是true            Class<?> targetType = determineTargetType(beanName, mbd);            if (targetType != null) {                bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);                if (bean != null) {                    bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);                }            }        }        mbd.beforeInstantiationResolved = (bean != null);    }    return bean;}mbd.isSynthetic()對於Pointcut 的bean來說是true的!很明顯,如果在這裡就返回bean 是不可能的。(2)下邊看看bean的建立BeanWrapper instanceWrapper = null;if (mbd.isSingleton()) {//如果是單例bean,從快取獲取    instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);}if (instanceWrapper == null) {    instanceWrapper = createBeanInstance(beanName, mbd, args);//真正建立例項;繼續看(3)}final Object bean = instanceWrapper.getWrappedInstance();final Object bean = instanceWrapper.getWrappedInstance();Class<?> beanType = instanceWrapper.getWrappedClass();//獲取例項化類的型別if (beanType != NullBean.class) {    mbd.resolvedTargetType = beanType;//設定到mdb}synchronized (mbd.postProcessingLock) {    if (!mbd.postProcessed) {        try {            applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);//呼叫MergedBeanDefinitionPostProcessor BPP處理        }        catch (Throwable ex) {            throw new BeanCreationException(mbd.getResourceDescription(), beanName,                    "Post-processing of merged bean definition failed", ex);        }        mbd.postProcessed = true;    }}boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&isSingletonCurrentlyInCreation(beanName));//預設允許處理迴圈引用;這個bool表示式表示:在預設情況下,如果單例bean已經在建立了的情況;這應該是迴圈引用場景下,又嘗試初始化mbdif (earlySingletonExposure) {    if (logger.isDebugEnabled()) {        logger.debug("Eagerly caching bean '" + beanName +                "' to allow for resolving potential circular references");    }    addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));//為mbd設定工廠類}Object exposedObject = bean;try {    populateBean(beanName, mbd, instanceWrapper);//增強處理(10)    exposedObject = initializeBean(beanName, exposedObject, mbd);//增強處理(10)}(3) 例項建立,策略有:factory method, constructor autowiring, or simple instantiation.這裡只要介紹3種:if (mbd.getFactoryMethodName() != null)  {return instantiateUsingFactoryMethod(beanName, mbd, args);//設定了工廠方法,使用工廠方法建立例項;參見(4)}if (autowireNecessary) {    return autowireConstructor(beanName, mbd, null, null);//自動繫結構造方法;參見(5)}else {    return instantiateBean(beanName, mbd);//普通建立方法;參見(6)}(4)工廠方法建立例項工廠方法建立例項包括兩種情況:指定了工廠類bean或者工廠方法就是需要建立例項的bean的static方法最終呼叫的方法是:strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);(5)自動選擇構造方法根據呼叫getBean()時指定的引數型別或者配置在bean定義中的引數型別,自動選擇構造方法,然後呼叫:strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);(6)普通情況呼叫instantiate(mbd, beanName, parent);parent是當前容器例項;這裡的strategy就是AbstractAutowireCapableBeanFactory類的instantiationStrategy屬性:InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();初始化方法從CglibSubclassingInstantiationStrategy的父類SimpleInstantiationStrategy開始,先看instantiate(mbd, beanName, parent);public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {    // Don't override the class with CGLIB if no overrides.    if (!bd.hasMethodOverrides()) {//不需要方法過載時,不需要用CGLIB        Constructor<?> constructorToUse;//這裡省略掉的程式碼就是獲取構造方法        return BeanUtils.instantiateClass(constructorToUse);//建立例項;參見(7)    }    else {//用CGLIB實現子類        // Must generate CGLIB subclass.        return instantiateWithMethodInjection(bd, beanName, owner);//在子類中實現;參見(8)    }}再來看strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,final Constructor<?> ctor, @Nullable Object... args) {    if (!bd.hasMethodOverrides()) {        return (args != null ? BeanUtils.instantiateClass(ctor, args) : BeanUtils.instantiateClass(ctor));//參看(7)    }    else {        return instantiateWithMethodInjection(bd, beanName, owner, ctor, args);//CGLIB,在子類中實現;參見(8)    }}(7) 建立例項,核心程式碼就是try {    ReflectionUtils.makeAccessible(ctor);    return (KotlinDetector.isKotlinType(ctor.getDeclaringClass()) ?            KotlinDelegate.instantiateClass(ctor, args) : ctor.newInstance(args));}(8) CGLIB怎麼建立例項的?return new CglibSubclassCreator(bd, owner).instantiate(ctor, args);呼叫內部類是實現,看內部類的程式碼:public Object instantiate(@Nullable Constructor<?> ctor, @Nullable Object... args) {    Class<?> subclass = createEnhancedSubclass(this.beanDefinition);//參見(9)    Object instance;    if (ctor == null) {        instance = BeanUtils.instantiateClass(subclass);//參見(7)    }    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);        }    }    Factory factory = (Factory) instance;//直接在instance上設定Callbacks,而不是在enhancer物件上,是為了避免記憶體溢位    factory.setCallbacks(new Callback[] {NoOp.INSTANCE,            new LookupOverrideMethodInterceptor(this.beanDefinition, this.owner),            new ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)});    return instance;//返回生成的例項}(9) 獲取增強子類private Class<?> createEnhancedSubclass(RootBeanDefinition beanDefinition) {    Enhancer enhancer = new Enhancer();//增強工具類    enhancer.setSuperclass(beanDefinition.getBeanClass());//設定父類    enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);//設定命名策略,是一個SpringNamingPolicy物件    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);//繼承方法攔截處理,包括兩個內部類:LookupOverrideMethodInterceptor ReplaceOverrideMethodInterceptor;後邊直接在例項上設定callbacks    return enhancer.createClass();//建立增強類的Class物件}(10) BPP在這裡是否能參與增強bean例項呢?方法的說明:applying factory callbacks as well as init methods and bean post processors,就是使用init方法,BPP,工廠回撥方法初始化例項。populateBean方法:
boolean continueWithPropertyPopulation = true;if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {//如果設定了 InstantiationAwareBeanPostProcessors    for (BeanPostProcessor bp : getBeanPostProcessors()) {        if (bp instanceof InstantiationAwareBeanPostProcessor) {            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;            if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {//執行例項化後處理方法                continueWithPropertyPopulation = false;                break;            }        }    }}精簡的程式碼:protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {    invokeAwareMethods(beanName, bean);//繫結方法,主要為Aware子類設定beanName beanClassLoader beanFactory    Object wrappedBean = bean;    if (mbd == null || !mbd.isSynthetic()) {//預設Synthetic==false;表示不是組裝類;所以這個bool表示式是true的        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);//執行BPP的前處理方法    }    try {        invokeInitMethods(beanName, wrappedBean, mbd);//呼叫init方法初始化    }    if (mbd == null || !mbd.isSynthetic()) {        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);//執行BPP的後處理方法    }    return wrappedBean;}下邊先看看容器中BPP的情況。public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {    Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");    this.beanPostProcessors.remove(beanPostProcessor);    this.beanPostProcessors.add(beanPostProcessor);    if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {        this.hasInstantiationAwareBeanPostProcessors = true;    }    if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {        this.hasDestructionAwareBeanPostProcessors = true;    }}由addBeanPostProcessor可知,如果bean定義解析過程中設定了InstantiationAwareBeanPostProcessor型別的BPP,那麼hasInstantiationAwareBeanPostProcessors()將返回true。那麼什麼情況下會設定InstantiationAwareBeanPostProcessor型別的BPP呢?在AbstractApplicationContext.prepareBeanFactory(beanFactory);方法中會設定如下3個BPP:ApplicationContextAwareProcessorApplicationListenerDetectorLoadTimeWeaverAwareProcessor但是這3個都不是InstantiationAwareBeanPostProcessor型別的;其他的呢?AbstractApplicationContext.refresh()方法執行到下邊這一行時,實際的呼叫過程是把所有BeanPostProcessor的Bean全部例項化;然後每一個都呼叫addBeanPostProcessor方法;// Register bean processors that intercept bean creation.registerBeanPostProcessors(beanFactory);由自動代理bean的註冊過程可知,如果我們配置了<aop:config> 或者<aop: aspectj-autoproxy>或者<tx:annotation-driven>標籤,那麼一定會註冊一個InstantiationAwareBeanPostProcessor型別的bean:id="org.springframework.aop.config.internalAutoProxyCreator"class=AnnotationAwareAspectJAutoProxyCreator或者AspectJAwareAdvisorAutoProxyCreator或者InfrastructureAdvisorAutoProxyCreator其中AnnotationAwareAspectJAutoProxyCreator是AspectJAwareAdvisorAutoProxyCreator的子類,且3個類的父類繼承體系也是一樣的;總的來說,這三個標籤都能開啟spring的aop功能。
先看看這3個公共的BPP是怎麼執行的?ApplicationContextAwareProcessor的前處理方法的核心邏輯在下邊的方法中:private void invokeAwareInterfaces(Object bean) {    if (bean instanceof Aware) {        if (bean instanceof EnvironmentAware) {            ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());        }        if (bean instanceof EmbeddedValueResolverAware) {            ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);        }        if (bean instanceof ResourceLoaderAware) {            ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);        }        if (bean instanceof ApplicationEventPublisherAware) {            ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);        }        if (bean instanceof MessageSourceAware) {            ((MessageSourceAware) bean).setMessageSource(this.applicationContext);        }        if (bean instanceof ApplicationContextAware) {            ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);        }    }}後處理方法直接返回原物件;ApplicationListenerDetector處理ApplicationListener bean ,但是邏輯簡單,這裡先忽略;LoadTimeWeaverAwareProcessor的前處理方法如下:public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {    if (bean instanceof LoadTimeWeaverAware) {//只處LoadTimeWeaverAware型別的bean        LoadTimeWeaver ltw = this.loadTimeWeaver;        if (ltw == null) {            Assert.state(this.beanFactory != null,                    "BeanFactory required if no LoadTimeWeaver explicitly specified");            ltw = this.beanFactory.getBean(ConfigurableApplicationContext.LOAD_TIME_WEAVER_BEAN_NAME, LoadTimeWeaver.class);           //這裡要獲取id="loadTimeWeaver"的bean,根據load-time-weaver標籤的解析講解知道:要麼配置了load-time-weaver標籤要麼手動配置了id="loadTimeWeaver"的bean;否則,這裡獲取物件會失敗        }        ((LoadTimeWeaverAware) bean).setLoadTimeWeaver(ltw);//這一句就是LoadTimeWeaverAwareProcessor的意義所在,為所有LoadTimeWeaverAware型別的物件設定LTW weaver    }    return bean;}後處理方法直接返回原物件;再看AOP自動代理類的BPP對bean的代理處理過程:populateBean方法執行父類AbstractAutoProxyCreator中postProcessAfterInstantiation方法,如下:public boolean postProcessAfterInstantiation(Object bean, String beanName) {    return true;}但是什麼都沒有做!initializeBean方法執行父類AbstractAutoProxyCreator中postProcessBeforeInitialization,但是前處理方法直接返回原物件;再看執行postProcessAfterInitialization方法,程式碼如下:
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {    if (bean != null) {//bean是建立的物件,bean!==null為true        Object cacheKey = getCacheKey(bean.getClass(), beanName);//如果beanName是null或者長度為0,就返回beanClass;否則,如果是FactoryBean就返回"&"+beanName,否則返回beanName        if (!this.earlyProxyReferences.contains(cacheKey)) {//            return wrapIfNecessary(bean, beanName, cacheKey);//生成增強的子類的代理物件,主要就是處理bean配置的interceptors        }    }    return bean;}AbstractAutoProxyCreator類的wrapIfNecessary方法:protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {    if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {//如果已經存在,就直接返回        return bean;    }    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {//如果已經存在,就直接返回        return bean;    }    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {//判斷是否是基本的型別或者是否是可以跳過的bean;參見(11)        this.advisedBeans.put(cacheKey, Boolean.FALSE);        return bean;    }    // Create proxy if we have advice.    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);//獲取能夠處理目標類的advisor,這裡的bean.getClass()方法返回的是當前物件的類,需要說明的是:如果是第一個BPP,那麼就是原始指定的被代理類,否則,這裡得到的就是上一次代理物件對應的類;邏輯見《AOP Proxy 物件建立過程》(1)    if (specificInterceptors != DO_NOT_PROXY) {//存在需要處理的advisor時,使用代理        this.advisedBeans.put(cacheKey, Boolean.TRUE);//有advisor的bean物件,value=true        Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));//Create an AOP proxy for the given bean,分析見《AOP Proxy 物件建立過程》(2)        this.proxyTypes.put(cacheKey, proxy.getClass());        return proxy;    }    this.advisedBeans.put(cacheKey, Boolean.FALSE);//沒有advisor的bean物件,value=false    return bean;}(11) 如下型別或者這些型別的子類的物件被稱為基本型別Advice.classPointcut.classAdvisor.classAopInfrastructureBean.classshouldSkip()在AspectJAwareAdvisorAutoProxyCreator中實現,邏輯就是beanName如果是advisor切面的名字就跳過,也就是不處理切面bean;接著就是代理物件的處理過程了,請看《AOP Proxy 物件建立過程》。