Springboot中註解@Configuration原始碼分析

wang03發表於2021-07-25

Springboot中註解@Configuration和@Component的區別

1.先說結論,@Configuration註解上面有@Component註解,所以@Component有的功能@Configuration都有。@Configuration生成的bean是一個代理物件,具體@Configuration的實現如何我們現在就開啟原始碼來看看它。

2.部落格的程式碼路徑:程式碼路徑

生成的代理類class檔案路徑:generate-class.zip

你自己執行工程也會在target/classes/generate-class目錄下生成代理類class程式碼

3.@Configuration原始碼分析

由於@SpringBootApplication註解上有@Configuration,為了程式碼簡單,我們就直接看主類SpringbootconfigurationApplication就可以了。

@Configuration註解的類會進入ConfigurationClassPostProcessor.enhanceConfigurationClasses方法去生成代理類。

	public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
		......
		ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
		for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
			AbstractBeanDefinition beanDef = entry.getValue();
			// If a @Configuration class gets proxied, always proxy the target class
			beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
			// Set enhanced subclass of the user-specified bean class
            //configClass就是原始的類
			Class<?> configClass = beanDef.getBeanClass();
            //enhancedClass就是生成的代理類
			Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
			if (configClass != enhancedClass) {
				if (logger.isTraceEnabled()) {
					logger.trace(String.format("Replacing bean definition '%s' existing class '%s' with " +
							"enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName()));
				}
				beanDef.setBeanClass(enhancedClass);
			}
		}
		enhanceConfigClasses.tag("classCount", () -> String.valueOf(configBeanDefs.keySet().size())).end();
	}

生成代理類主要就是enhancer.enhance(configClass, this.beanClassLoader)這句了,下面我們自己去看看

	public Class<?> enhance(Class<?> configClass, @Nullable ClassLoader classLoader) {
		......
        //關鍵程式碼也就這一行了,首先建立一個Enhancer物件,然後呼叫createClass方法
		Class<?> enhancedClass = createClass(newEnhancer(configClass, classLoader));
		......
		return enhancedClass;
	}
	private Enhancer newEnhancer(Class<?> configSuperClass, @Nullable ClassLoader classLoader) {
		Enhancer enhancer = new Enhancer();
        //設定生成代理類的父類,就是我們原始的類
		enhancer.setSuperclass(configSuperClass);
        //設定代理類實現的介面
		enhancer.setInterfaces(new Class<?>[] {EnhancedConfiguration.class});
		enhancer.setUseFactory(false);
        //設定代理類名的生成策略
		enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
        //設定代理類的生成策略
		enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));
        //設定代理類要重寫的方法,對類中@Bean的方法和對實現了BeanFactoryAware介面的setBeanFactory進行重寫,也就是代理
		enhancer.setCallbackFilter(CALLBACK_FILTER);
		enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
		return enhancer;
	}

在這裡我們還需要Enhancer類中的屬性KEY_FACTORY,由於它是靜態屬性,所以在載入Enhancer類的時候就會執行下面的程式碼

	//代理類會實現EnhancerKey介面,繼承KeyFactory(KEY_FACTORY是代理類的物件)
	private static final EnhancerKey ,KEY_FACTORY =
			(EnhancerKey) KeyFactory.create(EnhancerKey.class, KeyFactory.HASH_ASM_TYPE, null);

這個KEY_FACTORY其實也是一個代理類的例項。我們就先看看它吧,這個主要是生成快取的key,不感興趣也可以跳過下面KEY_FACTORY的生成部分

KEY_FACTORY的生成

	public static KeyFactory create(ClassLoader loader, Class keyInterface, KeyFactoryCustomizer customizer,
			List<KeyFactoryCustomizer> next) {
		Generator gen = new Generator();
		gen.setInterface(keyInterface);
		// SPRING PATCH BEGIN
		gen.setContextClass(keyInterface);
		// SPRING PATCH END

		if (customizer != null) {
			gen.addCustomizer(customizer);
		}
		if (next != null && !next.isEmpty()) {
			for (KeyFactoryCustomizer keyFactoryCustomizer : next) {
				gen.addCustomizer(keyFactoryCustomizer);
			}
		}
		gen.setClassLoader(loader);
        //主要是這句,我們繼續走進去看看
		return gen.create();
	}

		public KeyFactory create() {
			//這裡是設定類名的字首
			setNamePrefix(keyInterface.getName());
			//繼續跟進去
			return (KeyFactory) super.create(keyInterface.getName());
		}
	protected Object create(Object key) {
		try {
            //這裡有個二級快取,首先根據getClassLoader()去找,然後根據ClassLoaderData的lambda表示式GET_KEY去找,這裡就是入參key了
			ClassLoader loader = getClassLoader();
			Map<ClassLoader, ClassLoaderData> cache = CACHE;
			ClassLoaderData data = cache.get(loader);
			if (data == null) {
				synchronized (AbstractClassGenerator.class) {
					cache = CACHE;
					data = cache.get(loader);
					if (data == null) {
						Map<ClassLoader, ClassLoaderData> newCache = new WeakHashMap<ClassLoader, ClassLoaderData>(cache);
						data = new ClassLoaderData(loader);
						newCache.put(loader, data);
						CACHE = newCache;
					}
				}
			}
			this.key = key;
            //這裡就會生成真正的類,我們走進去
			Object obj = data.get(this, getUseCache());
			if (obj instanceof Class) {
                //在這裡生成代理類的物件
				return firstInstance((Class) obj);
			}
			return nextInstance(obj);
		}
		catch (RuntimeException | Error ex) {
			throw ex;
		}
		catch (Exception ex) {
			throw new CodeGenerationException(ex);
		}
	}

這就會走到AbstractClassGenerator.ClassLoaderData的get方法

		public Object get(AbstractClassGenerator gen, boolean useCache) {
			if (!useCache) {
				return gen.generate(ClassLoaderData.this);
			}
			else {
                //我們傳入的useCache是true,會走這裡,再進去
				Object cachedValue = generatedClasses.get(gen);
				return gen.unwrapCachedValue(cachedValue);
			}
		}

現在走到了LoadingCache.get方法

    public V get(K key) {
        	//這裡的cacheKey就是org.springframework.cglib.proxy.Enhancer$EnhancerKey
        KK cacheKey = this.keyMapper.apply(key);
        Object v = this.map.get(cacheKey);
        我們這裡是第一次建立,所以會走到 this.createEntry(key, cacheKey, v)
        return v != null && !(v instanceof FutureTask) ? v : this.createEntry(key, cacheKey, v);
    }

···

protected V createEntry(final K key, KK cacheKey, Object v) {
    boolean creator = false;
    FutureTask task;
    Object result;
    if (v != null) {
        task = (FutureTask)v;
    } else {
        task = new FutureTask(new Callable<V>() {
            public V call() throws Exception {
                //真正的執行會在這裡,這裡會是一個單獨的執行緒,LoadingCache.this.loader是在ClassLoaderData的構造方法定義的lambda表示式,我們進去看看
                return LoadingCache.this.loader.apply(key);
            }
        });
        result = this.map.putIfAbsent(cacheKey, task);
        if (result == null) {
            creator = true;
            //在這裡開啟執行緒呼叫
            task.run();
        } else {
            if (!(result instanceof FutureTask)) {
                return result;
            }

            task = (FutureTask)result;
        }
    }

    try {
        //在這裡掛起,等待執行緒返回結果
        result = task.get();
    } catch (InterruptedException var9) {
        throw new IllegalStateException("Interrupted while loading cache item", var9);
    } catch (ExecutionException var10) {
        Throwable cause = var10.getCause();
        if (cause instanceof RuntimeException) {
            throw (RuntimeException)cause;
        }

        throw new IllegalStateException("Unable to load cache item", cause);
    }

    if (creator) {
        //建立成功,就會在這裡加入到快取中
        this.map.put(cacheKey, result);
    }

    return result;
}
			Function<AbstractClassGenerator, Object> load =
					new Function<AbstractClassGenerator, Object>() {
						public Object apply(AbstractClassGenerator gen) {
                            //這裡又會回到KeyFactory.Generator這個內部類中,這個方法在它的父類AbstractClassGenerator中,我們走進去
							Class klass = gen.generate(ClassLoaderData.this);
							return gen.wrapCachedClass(klass);
						}
					};

AbstractClassGenerator的generate方法

protected Class generate(ClassLoaderData data) {
			......
		try {
			......
			synchronized (classLoader) {
				//這裡生成類的名字
				String name = generateClassName(data.getUniqueNamePredicate());
				data.reserveName(name);
				this.setClassName(name);
			}
			......
			//在這裡生成類的byte[]檔案,繼續走進去
			byte[] b = strategy.generate(this);
            //這個是從位元組碼中獲取類名
            //在工程springbootconfiguration\target\classes\generate-class這個目錄下,根據className+".class"就能找到我們生成的class檔案(注意將包名的.換成路徑分割線)
			String className = ClassNameReader.getClassName(new ClassReader(b));
			ProtectionDomain protectionDomain = getProtectionDomain();
			synchronized (classLoader) { // just in case
				// SPRING PATCH BEGIN
				//將生成的類的檔案載入進jvm
				gen = ReflectUtils.defineClass(className, b, classLoader, protectionDomain, contextClass);
				// SPRING PATCH END
			}
			return gen;
		}
		......
	}

DefaultGeneratorStrategy的generate方法

    //真正生成類檔案的程式碼就在這裡,這個是通過asm來生成的,具體asm這塊就不再往裡面看了,關於asm這塊是個單獨的知識點,不過對我們來說,不看裡面細節也不影響我們的分析,我們main方法中有 System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,p);,就會將生成的class檔案儲存到本地,我們直接看這個就好了,我們當前生成的class檔案統一放到了springbootconfiguration\target\classes\generate-class這個目錄下
    public byte[] generate(ClassGenerator cg) throws Exception {
        DebuggingClassWriter cw = this.getClassVisitor();
        this.transform(cg).generateClass(cw);
        return this.transform(cw.toByteArray());
    }

下面這個就是我本地生成的class檔案反編譯後的java程式碼

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.springframework.cglib.proxy;

import org.springframework.asm.Type;
import org.springframework.cglib.core.KeyFactory;
import org.springframework.cglib.core.WeakCacheKey;
import org.springframework.cglib.proxy.Enhancer.EnhancerKey;

public class Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$4ce19e8f extends KeyFactory implements EnhancerKey {
    private final String FIELD_0;
    private final String[] FIELD_1;
    private final WeakCacheKey FIELD_2;
    private final Type[] FIELD_3;
    private final boolean FIELD_4;
    private final boolean FIELD_5;
    private final Long FIELD_6;

    public Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$4ce19e8f() {
    }

    public Object newInstance(String var1, String[] var2, WeakCacheKey var3, Type[] var4, boolean var5, boolean var6, Long var7) {
        return new Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$4ce19e8f(var1, var2, var3, var4, var5, var6, var7);
    }

    public Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$4ce19e8f(String var1, String[] var2, WeakCacheKey var3, Type[] var4, boolean var5, boolean var6, Long var7) {
        this.FIELD_0 = var1;
        this.FIELD_1 = var2;
        this.FIELD_2 = var3;
        this.FIELD_3 = var4;
        this.FIELD_4 = var5;
        this.FIELD_5 = var6;
        this.FIELD_6 = var7;
    }

    public int hashCode() {
        int var10002 = 1213 * 1209107;
        String var10001 = this.FIELD_0;
        int var10000 = var10002 + (var10001 != null ? var10001.hashCode() : 0);
        String[] var5 = this.FIELD_1;
        if (var5 != null) {
            String[] var1 = var5;

            for(int var2 = 0; var2 < var1.length; ++var2) {
                var10000 = var10000 * 1209107 + (var1[var2] != null ? var1[var2].hashCode() : 0);
            }
        }

        var10002 = var10000 * 1209107;
        WeakCacheKey var6 = this.FIELD_2;
        var10000 = var10002 + (var6 != null ? var6.hashCode() : 0);
        Type[] var7 = this.FIELD_3;
        if (var7 != null) {
            Type[] var3 = var7;

            for(int var4 = 0; var4 < var3.length; ++var4) {
                var10000 = var10000 * 1209107 + (var3[var4] != null ? var3[var4].hashCode() : 0);
            }
        }

        var10002 = ((var10000 * 1209107 + (this.FIELD_4 ^ 1)) * 1209107 + (this.FIELD_5 ^ 1)) * 1209107;
        Long var8 = this.FIELD_6;
        return var10002 + (var8 != null ? var8.hashCode() : 0);
    }

    public boolean equals(Object var1) {
        if (var1 instanceof Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$4ce19e8f) {
            String var10000 = this.FIELD_0;
            String var10001 = ((Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$4ce19e8f)var1).FIELD_0;
            if (var10001 == null) {
                if (var10000 != null) {
                    return false;
                }
            } else if (var10000 == null || !var10000.equals(var10001)) {
                return false;
            }

            String[] var8 = this.FIELD_1;
            String[] var10 = ((Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$4ce19e8f)var1).FIELD_1;
            if (var10 == null) {
                if (var8 != null) {
                    return false;
                }
            } else {
                label178: {
                    if (var8 != null) {
                        if (var10.length == var8.length) {
                            String[] var2 = var10;
                            String[] var3 = var8;
                            int var4 = 0;

                            while(true) {
                                if (var4 >= var2.length) {
                                    break label178;
                                }

                                var10000 = var2[var4];
                                var10001 = var3[var4];
                                if (var3[var4] == null) {
                                    if (var10000 != null) {
                                        return false;
                                    }
                                } else if (var10000 == null || !var10000.equals(var10001)) {
                                    return false;
                                }

                                ++var4;
                            }
                        }
                    }

                    return false;
                }
            }

            WeakCacheKey var9 = this.FIELD_2;
            WeakCacheKey var13 = ((Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$4ce19e8f)var1).FIELD_2;
            if (var13 == null) {
                if (var9 != null) {
                    return false;
                }
            } else if (var9 == null || !var9.equals(var13)) {
                return false;
            }

            Type[] var11 = this.FIELD_3;
            Type[] var15 = ((Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$4ce19e8f)var1).FIELD_3;
            if (var15 == null) {
                if (var11 != null) {
                    return false;
                }
            } else {
                if (var11 == null) {
                    return false;
                }

                if (var15.length != var11.length) {
                    return false;
                }

                Type[] var5 = var15;
                Type[] var6 = var11;

                for(int var7 = 0; var7 < var5.length; ++var7) {
                    Type var12 = var5[var7];
                    Type var16 = var6[var7];
                    if (var6[var7] == null) {
                        if (var12 != null) {
                            return false;
                        }
                    } else if (var12 == null || !var12.equals(var16)) {
                        return false;
                    }
                }
            }

            if (this.FIELD_4 == ((Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$4ce19e8f)var1).FIELD_4 && this.FIELD_5 == ((Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$4ce19e8f)var1).FIELD_5) {
                Long var14 = this.FIELD_6;
                Long var17 = ((Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$4ce19e8f)var1).FIELD_6;
                if (var17 == null) {
                    if (var14 == null) {
                        return true;
                    }
                } else if (var14 != null && var14.equals(var17)) {
                    return true;
                }
            }
        }

        return false;
    }

    public String toString() {
        StringBuffer var10000 = new StringBuffer();
        String var10001 = this.FIELD_0;
        var10000 = (var10001 != null ? var10000.append(var10001.toString()) : var10000.append("null")).append(", ");
        String[] var6 = this.FIELD_1;
        if (var6 != null) {
            var10000 = var10000.append("{");
            String[] var1 = var6;

            for(int var2 = 0; var2 < var1.length; ++var2) {
                var10000 = (var1[var2] != null ? var10000.append(var1[var2].toString()) : var10000.append("null")).append(", ");
            }

            var10000.setLength(var10000.length() - 2);
            var10000 = var10000.append("}");
        } else {
            var10000 = var10000.append("null");
        }

        var10000 = var10000.append(", ");
        WeakCacheKey var9 = this.FIELD_2;
        var10000 = (var9 != null ? var10000.append(var9.toString()) : var10000.append("null")).append(", ");
        Type[] var10 = this.FIELD_3;
        if (var10 != null) {
            var10000 = var10000.append("{");
            Type[] var3 = var10;

            for(int var4 = 0; var4 < var3.length; ++var4) {
                var10000 = (var3[var4] != null ? var10000.append(var3[var4].toString()) : var10000.append("null")).append(", ");
            }

            var10000.setLength(var10000.length() - 2);
            var10000 = var10000.append("}");
        } else {
            var10000 = var10000.append("null");
        }

        var10000 = var10000.append(", ").append(this.FIELD_4).append(", ").append(this.FIELD_5).append(", ");
        Long var13 = this.FIELD_6;
        return (var13 != null ? var10000.append(var13.toString()) : var10000.append("null")).toString();
    }
}

生成代理類呼叫的還是create方法中的程式碼

	protected Object create(Object key) {
			......
			if (obj instanceof Class) {
                //在這裡生成代理類的物件,呼叫代理類的無參構造方法生成代理類的物件
				return firstInstance((Class) obj);
			}
			return nextInstance(obj);
		}
		catch (RuntimeException | Error ex) {
			throw ex;
		}
		catch (Exception ex) {
			throw new CodeGenerationException(ex);
		}
	}

下面就是我本地生成的KEY_FACTORY物件

下面我們看看生成@Configuration代理類的程式碼

我們回到ConfigurationClassEnhancer的createClass方法,對這個不感興趣,也可以跳過這部分,直接看初始化@Configuration代理類部分

	private Class<?> createClass(Enhancer enhancer) {
		//這裡直接呼叫Enhancer的createClass方法,繼續走進去
		Class<?> subclass = enhancer.createClass();
		......
	}

Enhancer中會繼續調到createHelper方法

	private Object createHelper() {
		preValidate();
		//這就是根據上面生成代理類的物件生成key,根據這個key在快取中查詢
		Object key = KEY_FACTORY.newInstance((superclass != null) ? superclass.getName() : null,
				ReflectUtils.getNames(interfaces),
				filter == ALL_ZERO ? null : new WeakCacheKey<CallbackFilter>(filter),
				callbackTypes,
				useFactory,
				interceptDuringConstruction,
				serialVersionUID);
		this.currentKey = key;
		Object result = super.create(key);
		return result;
	}

後面很多程式碼都和上面KEY_FACTORY的生成是一樣的,主要是這裡會對方法進行一些過濾

生成代理類的時候具體要ConfigurationClassEnhancer.CALLBACK_FILTER確定代理方法的生成器

CALLBACK_FILTER中根據CALLBACKS來進行過濾,由於BeanMethodInterceptor,BeanFactoryAwareMethodInterceptor都是實現了MethodInterceptor, ConditionalCallback這兩個介面,CALLBACK_FILTER中就會直接使用ConditionalCallback.isMatch去判斷,其他的都會由NoOp.INSTANCE來處理。

BeanMethodInterceptor方法會過濾出來有@註解的方法,BeanFactoryAwareMethodInterceptor會過濾出來BeanFactoryAware.setBeanFactory方法

具體方法的生成器是在CallbackInfo中定義的

    static {
        CALLBACKS = new CallbackInfo[]{new CallbackInfo(NoOp.class, NoOpGenerator.INSTANCE), new CallbackInfo(MethodInterceptor.class, MethodInterceptorGenerator.INSTANCE), new CallbackInfo(InvocationHandler.class, InvocationHandlerGenerator.INSTANCE), new CallbackInfo(LazyLoader.class, LazyLoaderGenerator.INSTANCE), new CallbackInfo(Dispatcher.class, DispatcherGenerator.INSTANCE), new CallbackInfo(FixedValue.class, FixedValueGenerator.INSTANCE), new CallbackInfo(ProxyRefDispatcher.class, DispatcherGenerator.PROXY_REF_INSTANCE)};
    }

BeanMethodInterceptor,BeanFactoryAwareMethodInterceptor這兩個過濾器實現了MethodInterceptor介面,所以它們的方法生成器都是 MethodInterceptorGenerator.INSTANCE(會處理@註解的方法,BeanFactoryAwareMethodInterceptor會過濾出來BeanFactoryAware.setBeanFactory方法)

其他的都是由NoOp.INSTANCE來處理,方法生成器就是NoOpGenerator.INSTANCE(這個方法實際不會去生成位元組碼,所以直接上這些方法還是呼叫父類的方法)

最終生成的位元組碼是這個樣子的

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.example.springbootconfiguration;

import com.example.springbootconfiguration.entity.Home;
import com.example.springbootconfiguration.entity.User;
import java.lang.reflect.Method;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.cglib.core.ReflectUtils;
import org.springframework.cglib.core.Signature;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import org.springframework.cglib.proxy.NoOp;
import org.springframework.context.annotation.ConfigurationClassEnhancer.EnhancedConfiguration;

public class SpringbootconfigurationApplication$$EnhancerBySpringCGLIB$$d37254bc extends SpringbootconfigurationApplication implements EnhancedConfiguration {
    private boolean CGLIB$BOUND;
    public static Object CGLIB$FACTORY_DATA;
    private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
    private static final Callback[] CGLIB$STATIC_CALLBACKS;
    private MethodInterceptor CGLIB$CALLBACK_0;
    private MethodInterceptor CGLIB$CALLBACK_1;
    private NoOp CGLIB$CALLBACK_2;
    private static Object CGLIB$CALLBACK_FILTER;
    private static final Method CGLIB$getUser$0$Method;
    private static final MethodProxy CGLIB$getUser$0$Proxy;
    private static final Object[] CGLIB$emptyArgs;
    private static final Method CGLIB$getHome$1$Method;
    private static final MethodProxy CGLIB$getHome$1$Proxy;
    private static final Method CGLIB$setBeanFactory$6$Method;
    private static final MethodProxy CGLIB$setBeanFactory$6$Proxy;
    public BeanFactory $$beanFactory;

    static void CGLIB$STATICHOOK1() {
        CGLIB$THREAD_CALLBACKS = new ThreadLocal();
        CGLIB$emptyArgs = new Object[0];
        Class var0 = Class.forName("com.example.springbootconfiguration.SpringbootconfigurationApplication$$EnhancerBySpringCGLIB$$d37254bc");
        Class var1;
        CGLIB$setBeanFactory$6$Method = ReflectUtils.findMethods(new String[]{"setBeanFactory", "(Lorg/springframework/beans/factory/BeanFactory;)V"}, (var1 = Class.forName("org.springframework.beans.factory.BeanFactoryAware")).getDeclaredMethods())[0];
        CGLIB$setBeanFactory$6$Proxy = MethodProxy.create(var1, var0, "(Lorg/springframework/beans/factory/BeanFactory;)V", "setBeanFactory", "CGLIB$setBeanFactory$6");
        Method[] var10000 = ReflectUtils.findMethods(new String[]{"getUser", "()Lcom/example/springbootconfiguration/entity/User;", "getHome", "()Lcom/example/springbootconfiguration/entity/Home;"}, (var1 = Class.forName("com.example.springbootconfiguration.SpringbootconfigurationApplication")).getDeclaredMethods());
        CGLIB$getUser$0$Method = var10000[0];
        CGLIB$getUser$0$Proxy = MethodProxy.create(var1, var0, "()Lcom/example/springbootconfiguration/entity/User;", "getUser", "CGLIB$getUser$0");
        CGLIB$getHome$1$Method = var10000[1];
        CGLIB$getHome$1$Proxy = MethodProxy.create(var1, var0, "()Lcom/example/springbootconfiguration/entity/Home;", "getHome", "CGLIB$getHome$1");
    }

    final User CGLIB$getUser$0() {
        return super.getUser();
    }

    public final User getUser() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        return var10000 != null ? (User)var10000.intercept(this, CGLIB$getUser$0$Method, CGLIB$emptyArgs, CGLIB$getUser$0$Proxy) : super.getUser();
    }

    final Home CGLIB$getHome$1() {
        return super.getHome();
    }

    public final Home getHome() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        return var10000 != null ? (Home)var10000.intercept(this, CGLIB$getHome$1$Method, CGLIB$emptyArgs, CGLIB$getHome$1$Proxy) : super.getHome();
    }

    final void CGLIB$setBeanFactory$6(BeanFactory var1) throws BeansException {
        super.setBeanFactory(var1);
    }

    public final void setBeanFactory(BeanFactory var1) throws BeansException {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_1;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_1;
        }

        if (var10000 != null) {
            var10000.intercept(this, CGLIB$setBeanFactory$6$Method, new Object[]{var1}, CGLIB$setBeanFactory$6$Proxy);
        } else {
            super.setBeanFactory(var1);
        }
    }

    public static MethodProxy CGLIB$findMethodProxy(Signature var0) {
        String var10000 = var0.toString();
        switch(var10000.hashCode()) {
        case -964783719:
            if (var10000.equals("getUser()Lcom/example/springbootconfiguration/entity/User;")) {
                return CGLIB$getUser$0$Proxy;
            }
            break;
        case 1508184433:
            if (var10000.equals("getHome()Lcom/example/springbootconfiguration/entity/Home;")) {
                return CGLIB$getHome$1$Proxy;
            }
            break;
        case 2095635076:
            if (var10000.equals("setBeanFactory(Lorg/springframework/beans/factory/BeanFactory;)V")) {
                return CGLIB$setBeanFactory$6$Proxy;
            }
        }

        return null;
    }

    public SpringbootconfigurationApplication$$EnhancerBySpringCGLIB$$d37254bc() {
        CGLIB$BIND_CALLBACKS(this);
    }

    public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) {
        CGLIB$THREAD_CALLBACKS.set(var0);
    }

    public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] var0) {
        CGLIB$STATIC_CALLBACKS = var0;
    }

    private static final void CGLIB$BIND_CALLBACKS(Object var0) {
        SpringbootconfigurationApplication$$EnhancerBySpringCGLIB$$d37254bc var1 = (SpringbootconfigurationApplication$$EnhancerBySpringCGLIB$$d37254bc)var0;
        if (!var1.CGLIB$BOUND) {
            var1.CGLIB$BOUND = true;
            Object var10000 = CGLIB$THREAD_CALLBACKS.get();
            if (var10000 == null) {
                var10000 = CGLIB$STATIC_CALLBACKS;
                if (var10000 == null) {
                    return;
                }
            }

            Callback[] var10001 = (Callback[])var10000;
            var1.CGLIB$CALLBACK_2 = (NoOp)((Callback[])var10000)[2];
            var1.CGLIB$CALLBACK_1 = (MethodInterceptor)var10001[1];
            var1.CGLIB$CALLBACK_0 = (MethodInterceptor)var10001[0];
        }

    }

    static {
        CGLIB$STATICHOOK2();
        CGLIB$STATICHOOK1();
    }

    static void CGLIB$STATICHOOK2() {
    }
}

初始化@Configuration代理類

在上面生成了代理類位元組碼之後,就會將代理類位元組碼載入到jvm,生成代理類。

由於代理類中有static 靜態程式碼塊,所以這時就會去執行靜態程式碼塊(上面153行程式碼)

CGLIB$STATICHOOK2()的實現在158行,CGLIB$STATICHOOK1()的實現在39行,具體就不仔細看了。

執行完類載入後,會返回到ConfigurationClassEnhancer的createClass方法

	private Class<?> createClass(Enhancer enhancer) {
        //這裡就是生成代理類並載入
		Class<?> subclass = enhancer.createClass();
		// Registering callbacks statically (as opposed to thread-local)
		// is critical for usage in an OSGi environment (SPR-5932)...
        //這時會執行到這裡,會通過反射呼叫代理類的CGLIB$SET_STATIC_CALLBACKS(org.springframework.cglib.proxy.Callback[])方法將CALLBACKS設定上去,由於是靜態方法,所以不需要例項化物件可以直接呼叫
		Enhancer.registerStaticCallbacks(subclass, CALLBACKS);
		return subclass;
	}

到這裡代理類就基本完成了,後面就是生成bean物件了。

來生成對應bean的時候,會預設無參構造方法。

  public SpringbootconfigurationApplication$$EnhancerBySpringCGLIB$$d37254bc() {
        CGLIB$BIND_CALLBACKS(this);
    }

在CGLIB$BIND_CALLBACKS中主要會設定CGLIB$CALLBACK_x

    private static final void CGLIB$BIND_CALLBACKS(Object var0) {
			......
            Callback[] var10001 = (Callback[])var10000;
            var1.CGLIB$CALLBACK_2 = (NoOp)((Callback[])var10000)[2]; //NoOp.INSTANCE
            var1.CGLIB$CALLBACK_1 = (MethodInterceptor)var10001[1];  //new BeanFactoryAwareMethodInterceptor()
            var1.CGLIB$CALLBACK_0 = (MethodInterceptor)var10001[0];  //new BeanMethodInterceptor()
        }

    }

到這裡由代理類生成的bean就完成了,下面我們看看方法上@Bean生成的

生成代理類上@bean方法 表示的物件

我們這裡由兩個@Bean的方法

    @Bean
    public User getUser() {
        return new User();
    }

    @Bean
    public Home getHome() {
        return new Home(getUser());
    }

}

我們先看getUser的執行吧

    public final User getUser() {
        //這裡的var10000就是上面的new BeanMethodInterceptor()
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }
		//所以這裡會呼叫BeanMethodInterceptor.intercept進行返回
        return var10000 != null ? (User)var10000.intercept(this, CGLIB$getUser$0$Method, CGLIB$emptyArgs, CGLIB$getUser$0$Proxy) : super.getUser();
    }

BeanMethodInterceptor.intercept方法

public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
					MethodProxy cglibMethodProxy) throws Throwable {
			......	
			//這裡的beanMethod就是我們生成代理類的父類的getUser方法,當前beanFactory是正在建立它,所以會進到這個if分支,
			if (isCurrentlyInvokedFactoryMethod(beanMethod)) {
				......
                //這裡使用代理類中CGLIB$STATICHOOK1方法生成的代理方法去繼續呼叫,最終會呼叫代理類的CGLIB$getUser$1方法,繼續呼叫到父類的getUser()方法
               //在這呼叫過程中也會生成兩個快速查詢方法的類
               //1.SpringbootconfigurationApplication$$FastClassBySpringCGLIB$$fae3d721.class在我們的原始類中快速查詢方法
               //2.SpringbootconfigurationApplication$$EnhancerBySpringCGLIB$$43375915$$FastClassBySpringCGLIB$$c293f4a3在代理類中快速查詢方法     
				return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
			}

			return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
		}

下面我們來看看getHome的執行

    public final Home getHome() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        return var10000 != null ? (Home)var10000.intercept(this, CGLIB$getHome$1$Method, CGLIB$emptyArgs, CGLIB$getHome$1$Proxy) : super.getHome();
    }

還是呼叫BeanMethodInterceptor.intercept方法,前面的邏輯是和上面的一樣的,也會呼叫到CGLIB$getHome$0方法,繼續呼叫到父類的getHome();方法,這時由於父類getHome()方法中有呼叫getUser()方法,我們的代理類已經重寫了這個方法,這時又會回到代理類中getUser()繼而繼續呼叫BeanMethodInterceptor.intercept方法

		@Override
		@Nullable
		public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
					MethodProxy cglibMethodProxy) throws Throwable {
			......
            //由於beanFactory中我們正在建立的是getHome()這個方法,所以這時beanMethod=getUser()不會走到這個if分支
			if (isCurrentlyInvokedFactoryMethod(beanMethod)) {
				......
			}
			//所以會執行到這裡
			return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
		}

		private Object resolveBeanReference(Method beanMethod, Object[] beanMethodArgs,
				ConfigurableBeanFactory beanFactory, String beanName) {
			......
			try {
				......
                //由於之前已經執行過getUser 生成了bean物件,所以這裡會從beanFactory中獲取到對應的bean物件
				Object beanInstance = (useArgs ? beanFactory.getBean(beanName, beanMethodArgs) :
						beanFactory.getBean(beanName));
                ......
				//後面這就是獲取到當前正在建立的bean,新增依賴關係了
				Method currentlyInvoked = SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod();
				if (currentlyInvoked != null) {
					String outerBeanName = BeanAnnotationHelper.determineBeanNameFor(currentlyInvoked);
					beanFactory.registerDependentBean(beanName, outerBeanName);
				}
				return beanInstance;
			}
			finally {
				if (alreadyInCreation) {
					beanFactory.setCurrentlyInCreation(beanName, true);
				}
			}
		}

總結

@Configuration註解會生成代理類,代理類會繼承我的@Configuration註解所在的類,並實現EnhancedConfiguration介面。

會對@Bean,BeanFactoryAware.setBeanFactory(EnhancedConfiguration繼承了BeanFactoryAware介面)的方法在代理類中進行重寫,並用BeanMethodInterceptor.intercept進行攔截增強,多次呼叫@Bean的方法實際是返回的同一個物件,第一次呼叫時會生成物件,之後的呼叫都是會從beanFactory中獲取

相關文章