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

Springboot中注解@Configuration源码分析的更多相关文章

  1. Spring中Bean命名源码分析

    Spring中Bean命名源码分析 一.案例代码 首先是demo的整体结构 其次是各个部分的代码,代码本身比较简单,不是我们关注的重点 配置类 /** * @Author Helius * @Crea ...

  2. Springboot 加载配置文件源码分析

    Springboot 加载配置文件源码分析 本文的分析是基于springboot 2.2.0.RELEASE. 本篇文章的相关源码位置:https://github.com/wbo112/blogde ...

  3. Spring注解之@Lazy注解,源码分析和总结

    一 关于延迟加载的问题,有次和大神讨论他会不会直接或间接影响其他类.spring的好处就是文档都在代码里,网上百度大多是无用功. 不如,直接看源码.所以把当时源码分析的思路丢上来一波. 二 源码分析 ...

  4. Netty中的ChannelPipeline源码分析

    ChannelPipeline在Netty中是用来处理请求的责任链,默认实现是DefaultChannelPipeline,其构造方法如下: private final Channel channel ...

  5. BIZ中model.getSql源码分析

    功能:根据model.xml文件中配置的sql,获取对应的动态sql结果. 实例代码:String sql1 = model.getSql(dao.dbMeta());String sql2 = mo ...

  6. 【朝花夕拾】Android自定义View篇之(六)Android事件分发机制(中)从源码分析事件分发逻辑及经常遇到的一些“诡异”现象

    前言 转载请注明,转自[https://www.cnblogs.com/andy-songwei/p/11039252.html]谢谢! 在上一篇文章[[朝花夕拾]Android自定义View篇之(五 ...

  7. springBoot从入门到源码分析

    先分享一个springBoot搭建学习项目,和springboot多数据源项目的传送门:https://github.com/1057234721/springBoot 1. SpringBoot快速 ...

  8. DRF中的APIView源码分析

    首先写一个简单的drf接口 from rest_framework.views import APIView from rest_framework.response import Response ...

  9. Java并发包中CyclicBarrier的源码分析和使用

    CyclicBarrier的介绍和源码分析 CyclicBarrier的字母意思是可循环(Cyclic)使用的屏障(Barrier).它要做的事情是,让一组线程到达一个屏障(也可以叫做同步点)时被阻塞 ...

随机推荐

  1. Yolov4性能分析(上)

    Yolov4性能分析(上) 一.目录 实验测试 1) 测试介绍 2) Test 3) Train 二.   分析 1.实验测试 1. 1  实验测试方法 Yolov4训练train实验方法(Darkn ...

  2. pytest基础简介及实践举例

    一.pytest简介 pytest 是 python 的第三方单元测试框架,比自带的 unittest 更简洁和高效,同时兼容 unittest 框架.它还有如下优点: 1.简单灵活,容易上手,文档丰 ...

  3. Pandas高级教程之:Dataframe的合并

    目录 简介 使用concat 使用append 使用merge 使用join 覆盖数据 简介 Pandas提供了很多合并Series和Dataframe的强大的功能,通过这些功能可以方便的进行数据分析 ...

  4. 【Azure 机器人】微软Azure Bot 编辑器系列(1) : 创建一个天气对话机器人(The Bot Framework Composer tutorials)

    欢迎来到微软机器人编辑器使用教程,从这里开始,创建一个简单的机器人. 在该系列文章中,每一篇都将通过添加更多的功能来构建机器人.当完成教程中的全部内容后,你将成功的创建一个天气机器人(Weather ...

  5. 学废了系列 - WebGIS vs WebGL图形编程

    目前工作中有不少涉及到地图的项目,我参加了几次技术评审,前端伙伴们在 WebGIS 方面的知识储备稍有不足,这次分享的主要目的是科普一些在前端领域比较常用的 WebGIS 知识.另外,我之前的工作中积 ...

  6. 【NX二次开发】Block UI OrientXpress

    属性说明 属性   类型   描述   常规           BlockID    String    控件ID    Enable    Logical    是否可操作    Group    ...

  7. 【VBA】类型转换

    每个函数都可以强制将一个表达式转换成某种特定数据类型. 语法 CBool(expression) CByte(expression) CCur(expression) CDate(expression ...

  8. 【NX二次开发】开发环境搭建

    1.Visual Studio 版本按照下表选择. UG版本 VS版本 NX1847-NX1872版 Visual Studio 2017 Build 19.10.25017 NX12版 Visual ...

  9. Spring MVC 到 Spring BOOT 的简化之路

    背景 Spring vs Spring MVC vs Spring Boot Spring FrameWork Spring 还能解决什么问题 Spring MVC 为什么需要Spring Boot ...

  10. SpringBoot线程池的创建、@Async配置步骤及注意事项

    最近在做订单模块,用户购买服务类产品之后,需要进行预约,预约成功之后分别给商家和用户发送提醒短信.考虑发短信耗时的情况所以我想用异步的方法去执行,于是就在网上看见了Spring的@Async了. 但是 ...