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中獲取