Spring动态代理源码分析

6 篇文章 0 订阅
5 篇文章 0 订阅

        说到Spring的核心功能,Spring AOP是始终绕不过去的一个点。而说到Spring AOP,开发中我们经常会用到这个功能,比如:日志记录、权限校验、事务管理等。我们也大概知道它基于动态代理实现的,那除了Spring AOP,Spring还有哪些地方使用到了动态代理?Spring中的动态代理又是如何实现的?让我们跟着这篇文章来一探究竟。

一、代理模式

        代理模式是23中设计模式中比较常见的一种设计模式。代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。说简单点,代理模式就是设置一个中间代理来控制访问原目标对象,以达到增强原对象的功能和简化访问方式。通俗地来讲代理模式就是我们生活中常见的中介。

        Java中一般使用代理在不改变目标类的基础,对类做增强处理。其实代理可以改变目标类,但是我们一般都不会去这样做,算是一种约定俗成的做法。

        那我们就先来说说代理模式。代理模式分为静态代理和动态代理。

(1)静态代理

 (i)静态代理的实现

  • 继承
  • 继承+聚合

        静态代理的应用场景:进行代码升级,例如,在原来的功能模块上添加新的功能,我们可以不用修改原来的底层代码,只需要通过代理模式来进行代码迭代。

        例如:系统原来只是简单的实现了登录功能。

  public class Service {
  ​
      public void login(){
          System.out.println("doLogin……");
      }
  }

        第一次更新后,加入了权限校验模块。

public class CheckService extends Service{
  ​
  ​
      private Service target;
  ​
      public CheckService(Service target) {
          this.target = target;
      }
  ​
      @Override
      public void login() {
          System.out.println("authentication……");
          target.login();
      }
  }

        第二次更新,增加了日志模块。

 public class LogService extends Service{
  ​
  ​
      private Service target;
  ​
      public LogService(Service service) {
          this.target = service;
      }
  ​
      @Override
      public void login() {
          System.out.println("print Logging……");
          target.login();
      }
  }

        系统更新后,只需要修改很少的主体代码就可以实现代码升级。

  
   public static void main(String[] args) {
          Service service = new Service();
          // 第一次更新
          Service checkService = new CheckService(service);
          checkService.login();
  
          // 第二次更新​
          Service loginService = new LogService(checkService);
          loginService.login();
  ​
      }

        但更多的时候是,第二次更新时,第一次更新的就被舍弃了,随着系统的迭代,舍弃的代码会越来越多。

        上面的代码可能表达的比较隐晦,我们使用下面的方式实现静态代理多一些。

public interface IService {

    void process();

}

//实际处理类
public class TargetService implements IService {

    public void process(){
    
        System.out.println("TargetService ……");
    }


}


public class ProxyService implements IService {

    private IService target;

    public ProxyService(IService target){
        
        this.target = target;

    }

    public void process(){
    
        System.out.println("before Proxy doing ……");
        target.process();
        System.out.println("after Proxy doing ……");
        
    }


}

main(){
    
    TargetService target = new TargetService();
    ProxyService proxy = new ProxyService(target);
    proxy.process();

}



(ii)静态代理的优缺点

        优点:可以在不修改目标对象的前提下扩展目标对象的功能。

        缺点:如果需要代理多个类,每个类都会有一个代理类,会导致代理类无限制扩展;如果类中有多个方法,同样的代理逻辑需要反复实现、应用到每个方法上,一旦接口或基类增加方法,目标对象与代理对象都要进行修改。

(2)动态代理

        (i)JDK动态代理

        JDK动态代理原理:利用拦截器(必须实现InvocationHandler)加上反射机制生成一个代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。JDK动态代理是基于接口实现代理的,如果代理对象是类,那JDK无法进行代理。

        JDK动态代理的一般步骤:

        ​ A.定义一个接口

​         B.创建InvocationHandler接口的实现类,实现invoke()方法。

​         C.调用Proxy.newProxyInstance()方法创建代理对象

public interface IService{

    void process();

}

public class CoreService implements IService{


    public void process(){
    
        System.out.println("[target] CoreService's process()...");
    }


}

public class JdkInvocationHandler implements InvocationHandler {

    //目标类
    private Object targetObj;

    public JdkInvocationHandler(Object targetObj) {
        this.targetObj = targetObj;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        String name = method.getName();

        System.out.println("[JDK]method = " + name + ", args = " + Arrays.deepToString(args));
        System.out.println("[JDK]mmethod: " + name + " before doing...");


        //代理对象
        Object returnValue = method.invoke(targetObj, args);

        System.out.println("[JDK]mmethod: " + name + " after doing...");

        return returnValue;
    }
}
public class ProxyTest {

    public static void main(String[] args) {
        
        //目标类
        CoreService coreService = new CoreService();

        InvocationHandler jdkInvocationHandler = new JdkInvocationHandler(coreService );

        IService proxyService = (IService)Proxy.newProxyInstance(ProxyTest.class.getClassLoader(), new Class<?>[]{IService.class}, jdkInvocationHandler);

}

        (ii)CGLIB动态代理

        CGLIB动态代理原理:利用ASM框架,将代理对象类生成的class文件加载进来,通过修改其字节码生成子类完成对目标对象的代理。CGLIB既可以代理类,也可以代理接口。

        CGLIB动态代理的一般步骤:

        A.定义一个类

        B.创建MethodInterceptor接口的实现类,实现intercept()方法。

        C.创建CGLIB代理增强器Enhancer,通过其create()方法创建代理对象

public class Service{


    pubilc void process(){
    
        System.out.println("[target] class Service's process()...");

    }


}



public class CustomerCglibMethodInterceptor implements MethodInterceptor {
	@Override
	public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {

		 String methodName = method.getName();

        System.out.println("method = " + methodName + " ,args= " + Arrays.deepToString(objects));

        System.out.println("[CGLIB]method = " + methodName + " ,before doing... ");

        // 代理对象
        Object invoke = methodProxy.invokeSuper(o, objects);
        System.out.println("[CGLIB]method = " + methodName + " ,after doing... ");
		
		return invoke;
	}
}



main{

    // 增强器
    Enhancer enhancer = new Enhancer();
    // 设置目标代理类
    enhancer.setSuperclass(Service.class);
    // 设置Interceptor
    enhancer.setCallback(new CustomerCglibMethodInterceptor());
    // 创建代理对象
    Service service = (Service)enhancer.create();
    service.process();



}

        上面代码对所有的方法都执行同样的增强,如果我想对不同的方法实现不同的增强,例如:get开头的方法记录执行时间,set开头的方法记录详细日志。

        定义一个ConditionCallback接口,它继承MethodInterceptor并提供一个方法匹配的功能。

public interface ConditionCallback extends MethodInterceptor {

    boolean isMatch(Method method);
}

        定义两个MethodInterceptor实现类,提供两种不同的增强。

public class ConditionGetMethodInterceptor implements ConditionCallback{
    @Override
    public boolean isMatch(Method method) {
        // 处理get方法
        if(method.getName().startsWith("get")){
            return true;
        }
        return false;
    }

    // get方法记录执行时间
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        long start = System.currentTimeMillis();
        Object invokeSuper = methodProxy.invokeSuper(o, objects);
        System.out.println(String.format("方法%s执行时间:%d 毫秒",method.getName(),(System.currentTimeMillis() - start)));
        return invokeSuper;
    }
}


public class ConditionSetMethodInterceptor implements ConditionCallback{
    @Override
    public boolean isMatch(Method method) {
        if(method.getName().startsWith("set")){
            return true;
        }
        return false;
    }

    // set方法进行日志记录
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        String methodName = method.getName();

        System.out.println("method = " + methodName + " ,args= " + Arrays.deepToString(objects));
        System.out.println("method = " + methodName + " ,before doing... ");
        Object invoke = methodProxy.invokeSuper(o, objects);
        System.out.println("method = " + methodName + " ,after doing... ");

        return invoke;
    }
}

        定义一个CallbackFilter,在执行不同的方法时调用不同的MethodInterceptor进行增强。

public class ConditionFilter implements CallbackFilter {

    private final Callback[] callbacks;
    public ConditionFilter(Callback[] callbacks){
        this.callbacks = callbacks;
    }

    @Override
    public int accept(Method method) {
        for (int i = 0; i < callbacks.length; i++) {
            if (callbacks[i] instanceof ConditionCallback){
                if(((ConditionCallback) callbacks[i]).isMatch(method)){
                    return i;
                }
            }else {
                throw new IllegalStateException("No callback available for method " + method.getName());
            }
        }
        return 0;
    }
}

         需要注意的是,如果设置了callbacks,需要与callbackFilter配套使用,不然会报错。

 public static void main(String[] args) {
        
        // 实现多种增强效果
        Callback[] callbacks = new Callback[]{new ConditionGetMethodInterceptor(),new ConditionSetMethodInterceptor()};


        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(BasicService.class);
        enhancer.setCallbacks(callbacks);
        //和callbacks配套使用,不然会报错
        enhancer.setCallbackFilter(new ConditionFilter(callbacks));
        BasicService service = (BasicService)enhancer.create();
        service.getData();
        service.setSystemCache("zhangli",new Object());


    }

        通过上面的学习,我们对代理模式有了基本的了解, 也方便我们阅读Spring中关于动态代理部分的源码。

        

        (iii)JDK动态代理和CGLIB动态代理的区别?

  • JDK动态代理只能对实现了接口的类生成代理,而不能针对类。
  • CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,并覆盖其中方法的增强,但是因为采用的是继承,所以该类或方法最好不要生成final,对于final类或方法,是无法继承的。

二、Spring中代理的应用

        我们先来看一段代码。

        下面的A对象会实例化几次?两次

@Component
public class SpringProxy {


	@Bean
	public A a(){
		System.out.println("init A");
		return new A();
	}


	@Bean
	public B b(){
		a();
		System.out.println("init B");
		return new B();
	}

}

        看控制台的打印:、

init A
init A
init B

        可以看到a()方法被调用了两次,即A对象被创建了两次,按照我们的理解,既然我们把在a()方法上加了@Bean,那它就会生成对应的beanDefinition,相对于是Spring中的Bean了,默认情况下应该是单例的,那为什么a()方法被调用了两次(A对象实例化两次)。

        接下来,我们把类上的@Component注解由改成@Configuration注解,现在,发现a()方法只被调用了一次。这就符合我们的预期了,为什么会这样?那Spring中是如何实现的呢?

         记得上一篇文章我们已经阅读完解析@Component和@Configuration及@Bean注解的源码,好像也没有看到相关处理,除了会将全配置类的BD的属性CONFIGURATION_CLASS_ATTRIBUTE的值设置为CONFIGURATION_CLASS_FULL,属性,简洁配置类的BD的属性CONFIGURATION_CLASS_ATTRIBUTE的设置为CONFIGURATION_CLASS_LITE。(解析配置类源码分析)这其实也是Spring中代理的应用点之一,我们在上篇文章最后也提示了ConfigurationClassPostProcessor类的其中一个功能就是生成CGLIB代理对象,具体逻辑在BeanFactoryPostProcessor的接口方法postProcessBeanFactory()中实现的。话不多说,我们直接看源码吧!

源码分析

       Spring在ConfigurationClassPostProcessor类的postProcessBeanFactory()方法中实现动态代理的,该方法是BeanFactoryPostProcessor的接口方法。

        这个方法中完成配置类进行增强,生成对应的代理对象。同时添加一个ImportAwareBeanPostProcessor类型的后置处理器到容器中。

@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		int factoryId = System.identityHashCode(beanFactory);
		if (this.factoriesPostProcessed.contains(factoryId)) {
			throw new IllegalStateException(
					"postProcessBeanFactory already called on this post-processor against " + beanFactory);
		}
		this.factoriesPostProcessed.add(factoryId);
		if (!this.registriesPostProcessed.contains(factoryId)) {
			// BeanDefinitionRegistryPostProcessor hook apparently not supported...
			// Simply call processConfigurationClasses lazily at this point then.
			processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
		}
		//生成代理对象
        // 代码块一:对配置类进行增强
		enhanceConfigurationClasses(beanFactory);
		///添加一个ImportAwareBeanPostProcessor类型的后置处理器
		beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
	}

(1)代码块一:enhanceConfigurationClasses(),后置处理从一个BeanFactory查找到的配置类的BeanDefinitions,然后通过ConfigurationClassEnhancer增强候选对象。

        就是将容器中的所有符合要求的配置类找到(是否全配置类),放入候选集合,然后遍历候选集合,完成对应方法的增强,同时将代理对象的class设置为BD的beanClass属性的值。

/**后置处理从一个BeanFactory查找到的配置类的BeanDefinitions;
  * 然后通过{@link ConfigurationClassEnhancer}增强任何候选对象。
  * 候选状态由BeanDefinition属性元数据决定。
**/
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
		StartupStep enhanceConfigClasses = this.applicationStartup.start("spring.context.config-classes.enhance");
		// 存放候选的beanDefinition(全配置类才会添加到这个集合)
		Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
		for (String beanName : beanFactory.getBeanDefinitionNames()) {
			BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
			// 候选条件属性
			Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE);
			MethodMetadata methodMetadata = null;
			if (beanDef instanceof AnnotatedBeanDefinition) {
				// @Bean标记的方法生成的beanDefinition设置了这个值
				methodMetadata = ((AnnotatedBeanDefinition) beanDef).getFactoryMethodMetadata();
			}
			if ((configClassAttr != null || methodMetadata != null) && beanDef instanceof AbstractBeanDefinition) {
				// Configuration class (full or lite) or a configuration-derived @Bean method
				// -> resolve bean class at this point...
				AbstractBeanDefinition abd = (AbstractBeanDefinition) beanDef;
				if (!abd.hasBeanClass()) {
					try {
						// 确保beanClass被解析
						abd.resolveBeanClass(this.beanClassLoader);
					}
					catch (Throwable ex) {
						throw new IllegalStateException(
								"Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
					}
				}
			}
			//找到所有符合标准的全配置类
			if (ConfigurationClassUtils.CONFIGURATION_CLASS_FULL.equals(configClassAttr)) {
				if (!(beanDef instanceof AbstractBeanDefinition)) {
					throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" +
							beanName + "' since it is not stored in an AbstractBeanDefinition subclass");
				}
				else if (logger.isInfoEnabled() && beanFactory.containsSingleton(beanName)) {
					logger.info("Cannot enhance @Configuration bean definition '" + beanName +
							"' since its singleton instance has been created too early. The typical cause " +
							"is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor " +
							"return type: Consider declaring such methods as 'static'.");
				}
				//将全配置类放入map
				configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
			}
		}
		//
		if (configBeanDefs.isEmpty()) {
			// nothing to enhance -> return immediately
			enhanceConfigClasses.end();
			return;
		}
		if (IN_NATIVE_IMAGE) {
			throw new BeanDefinitionStoreException("@Configuration classes need to be marked as proxyBeanMethods=false. Found: " + configBeanDefs.keySet());
		}

		//创建配置类代理增强器
		ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
		//循环map,生成代理对象
		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
			//原始对象
			Class<?> configClass = beanDef.getBeanClass();
			//CGLIB代理是基于父类实现的(继承)
			//代理对象
			// 代码二:使用CGLIB代理对配置类进行增强
			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()));
				}
				//将生成的代理对象放入BD
				beanDef.setBeanClass(enhancedClass);
			}
		}
		enhanceConfigClasses.tag("classCount", () -> String.valueOf(configBeanDefs.keySet().size())).end();
	}

 (2)代码块二:enhance(),使用CGLIB代理对配置类进行增强。

public Class<?> enhance(Class<?> configClass, @Nullable ClassLoader classLoader) {
		//判断是否被代理过
		//spring生成的代理类实现类EnhancedConfiguration接口
		if (EnhancedConfiguration.class.isAssignableFrom(configClass)) {
			if (logger.isDebugEnabled()) {
				logger.debug(String.format("Ignoring request to enhance %s as it has " +
						"already been enhanced. This usually indicates that more than one " +
						"ConfigurationClassPostProcessor has been registered (e.g. via " +
						"<context:annotation-config>). This is harmless, but you may " +
						"want check your configuration and remove one CCPP if possible",
						configClass.getName()));
			}
			return configClass;
		}
		// 代码三:创建代理对象对应的class
		Class<?> enhancedClass = createClass(newEnhancer(configClass, classLoader));
		if (logger.isTraceEnabled()) {
			logger.trace(String.format("Successfully enhanced %s; enhanced class name is: %s",
					configClass.getName(), enhancedClass.getName()));
		}
		return enhancedClass;
	}

(3)代码块三:createClass(),创建代理增强器完成代理,并返回代理对象的class。

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)...
		// 代码四:注册回调函数
		Enhancer.registerStaticCallbacks(subclass, CALLBACKS);
		return subclass;
	}

(4)代码块四:registerStaticCallbacks(),注册回调函数。

        根据不同方法调用不同的Callback完成方法的增强。

  • BeanMethodInterceptor 对方法的Class类型不属于Object.class,且方法名为setFactoryBean(),同时方法上有@Bean注解的方法进行增强
  • BeanFactoryAwareMethodInterceptor 对方法名为setFactoryBean()且方法类型为BeanFactoryAware.class的方法进行增强。
  • NoOp.INSTANCE:无操作。
// 回调函数都是无状态的
private static final Callback[] CALLBACKS = new Callback[] {
			new BeanMethodInterceptor(),
			new BeanFactoryAwareMethodInterceptor(),
			NoOp.INSTANCE
	};




private static class BeanMethodInterceptor implements MethodInterceptor, ConditionalCallback {
……

       //Class类型不属于Object.class,不是setFactoryBean()且方法上有@Bean注解
		@Override
		public boolean isMatch(Method candidateMethod) {
			return (candidateMethod.getDeclaringClass() != Object.class &&
					!BeanFactoryAwareMethodInterceptor.isSetBeanFactory(candidateMethod) &&
					BeanAnnotationHelper.isBeanAnnotated(candidateMethod));
		}

……
}



private static class BeanFactoryAwareMethodInterceptor implements MethodInterceptor, ConditionalCallback {

		……
        // setBeanFactory()方法才会执行这部分的增强
		@Override
		public boolean isMatch(Method candidateMethod) {
			return isSetBeanFactory(candidateMethod);
		}

    // 方法名为setBeanFactory()且方法类型为BeanFactoryAware,才会执行这部分的增强
		public static boolean isSetBeanFactory(Method candidateMethod) {
			return (candidateMethod.getName().equals("setBeanFactory") &&
					candidateMethod.getParameterCount() == 1 &&
					BeanFactory.class == candidateMethod.getParameterTypes()[0] &&
					BeanFactoryAware.class.isAssignableFrom(candidateMethod.getDeclaringClass()));
		}

        ……

}

 public static void registerStaticCallbacks(Class generatedClass, Callback[] callbacks) {
        setCallbacksHelper(generatedClass, callbacks, "CGLIB$SET_STATIC_CALLBACKS");
    }

private static void setCallbacksHelper(Class type, Callback[] callbacks, String methodName) {
        try {
            // Callback中methodName对应的方法
            Method setter = getCallbacksSetter(type, methodName);
            setter.invoke((Object)null, callbacks);
        } catch (NoSuchMethodException var4) {
            throw new IllegalArgumentException(type + " is not an enhanced class");
        } catch (IllegalAccessException var5) {
            throw new CodeGenerationException(var5);
        } catch (InvocationTargetException var6) {
            throw new CodeGenerationException(var6);
        }
    }

private static Method getCallbacksSetter(Class type, String methodName) throws NoSuchMethodException {
        return type.getDeclaredMethod(methodName, Callback[].class);
    }

 (5)代码块五:newEnhancer(),创建CGLIB增强器完成代理。

//代码四:创建CGLIB代理增强器实例
	/**
	 * Creates a new CGLIB {@link Enhancer} instance.
	 */
	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));
		//设置用于增强CallbackFilter
		enhancer.setCallbackFilter(CALLBACK_FILTER);
		enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
		return enhancer;
	}

        这里CallbackFilter的作用我们在代码演示里面大概知道其用途了。

private static class ConditionalCallbackFilter implements CallbackFilter {

		private final Callback[] callbacks;

		private final Class<?>[] callbackTypes;

		// callbacks数组赋值
		public ConditionalCallbackFilter(Callback[] callbacks) {
			this.callbacks = callbacks;
			this.callbackTypes = new Class<?>[callbacks.length];
			for (int i = 0; i < callbacks.length; i++) {
				this.callbackTypes[i] = callbacks[i].getClass();
			}
		}

		// 根据不同的方法匹配不同的callback
		@Override
		public int accept(Method method) {
			for (int i = 0; i < this.callbacks.length; i++) {
				Callback callback = this.callbacks[i];
				if (!(callback instanceof ConditionalCallback) || ((ConditionalCallback) callback).isMatch(method)) {
					return i;
				}
			}
			throw new IllegalStateException("No callback available for method " + method.getName());
		}

		public Class<?>[] getCallbackTypes() {
			return this.callbackTypes;
		}
	}

三、BeanMethodInterceptor源码分析

        通过上面对CALLBACKS数组简单了解,其中包含一个BeanMethodInterceptor实例,也了解了系统中注入的两个MethodInterceptor的isMatch()方法,使用BeanMethodInterceptor进行的情况居多,它会对大部分@Bean方法进行增强。

        方法大致总结为:

         1)根据方法名推断beanName。默认值为方法名称,如果有配置name属性,只要一个值时为这个唯一值,有多个值时,取下标为0的值 。

        2)获取Bean方法对应的代理模式,默认为NO。

        3)检查所请求的bean是否是FactoryBean。如果是,创建一个子类完成代理。如果FactoryBean或其接口方法getObject()有一个被final修饰,如果是,存在如下两种情况。

        a.方法返回值类型为接口,通过JDK动态代理完成方法增强。

        b.如果返回值类型不是接口,无法完成代理,直接直接返回FactoryBean

        否则通过CGLIB代理完成方法增强。

        4)判断当前创建Bean的方法与实际调用的方法一致。比较线程本地变量存储的factoryMethod与当前方法是否一致。(方法名和参数列表一致)

        a.如果一致,通过CGLIB代理完成方法增强,会执行父类方法,即@Bean方法里面实例化对象的方法。

         b.如果不一致,根据当前调用方法对应的beanName和方法参数通过getBean获取相关实例beanInstance,设置该实例与factoryMethod对应的bean的依赖关系。返回这个实例对象。 

private static class BeanMethodInterceptor implements MethodInterceptor, ConditionalCallback {

		
		@Override
		@Nullable
		public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
					MethodProxy cglibMethodProxy) throws Throwable {

			ConfigurableBeanFactory beanFactory = getBeanFactory(enhancedConfigInstance);
			// 获取方法对应的beanName
			String beanName = BeanAnnotationHelper.determineBeanNameFor(beanMethod);

			// Determine whether this bean is a scoped-proxy
			if (BeanAnnotationHelper.isScopedProxy(beanMethod)) {
				String scopedBeanName = ScopedProxyCreator.getTargetBeanName(beanName);
				if (beanFactory.isCurrentlyInCreation(scopedBeanName)) {
					beanName = scopedBeanName;
				}
			}

			// 检查所请求的bean是否是FactoryBean。如果是,创建一个子类
			if (factoryContainsBean(beanFactory, BeanFactory.FACTORY_BEAN_PREFIX + beanName) &&
					factoryContainsBean(beanFactory, beanName)) {
				Object factoryBean = beanFactory.getBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName);
				if (factoryBean instanceof ScopedProxyFactoryBean) {
					// Scoped proxy factory beans are a special case and should not be further proxied
					//有作用域的代理工厂bean是一种特殊情况,不应该被进一步代理
				}
				else {
					// It is a candidate FactoryBean - go ahead with enhancement
					// 代码六:对候选FactoryBean进行增强
					return enhanceFactoryBean(factoryBean, beanMethod.getReturnType(), beanFactory, beanName);
				}
			}

			//代码块九:当前创建Bean的方法与实际调用的方法一致
			if (isCurrentlyInvokedFactoryMethod(beanMethod)) {
				// The factory is calling the bean method in order to instantiate and register the bean
				// (i.e. via a getBean() call) -> invoke the super implementation of the method to actually
				// create the bean instance.
				if (logger.isInfoEnabled() &&
						BeanFactoryPostProcessor.class.isAssignableFrom(beanMethod.getReturnType())) {
					logger.info(String.format("@Bean method %s.%s is non-static and returns an object " +
									"assignable to Spring's BeanFactoryPostProcessor interface. This will " +
									"result in a failure to process annotations such as @Autowired, " +
									"@Resource and @PostConstruct within the method's declaring " +
									"@Configuration class. Add the 'static' modifier to this method to avoid " +
									"these container lifecycle issues; see @Bean javadoc for complete details.",
							beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName()));
				}
				//调用父类方法创建bean
				return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
			}

			//当前创建bean的方法与实际调用的方法不一致
			/**例如:
			 * f(){
			 * e();
			 * }
			 * 在执行f()方法中调用了e()方法;
			 * 当前执行的是f()方法,在执行到e()时,实际调用了e(),就会执行resolveBeanReference
			 * 类似于beanMethod就是当前执行方法栈的栈顶方法,f()是这个方法栈
			 */
			return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
		}

(1)代码块六:enhanceFactoryBean(),完成通过FactroyBean方式创建的对象的代理。

        这个方法大概总结为:

      1) FactoryBean类及其getObject()方法是否被final修饰,如果这两个其中一个被final修饰。

                a.如果是方法的返回值是接口类型,则通过JDK动态代理完成方法增强

                b.不是接口类型,无法进行代理,直接返回FactoryBean。

        2)如果不被final修饰,通过CGLIB代理实现方法增强。

private Object enhanceFactoryBean(final Object factoryBean, Class<?> exposedType,
				final ConfigurableBeanFactory beanFactory, final String beanName) {

			try {
				Class<?> clazz = factoryBean.getClass();
				// 类是否被final修饰
				boolean finalClass = Modifier.isFinal(clazz.getModifiers());
				// factoryBean的getObject()方法是否被final修饰
				boolean finalMethod = Modifier.isFinal(clazz.getMethod("getObject").getModifiers());
				if (finalClass || finalMethod) {
					// 如果是接口
					if (exposedType.isInterface()) {
						if (logger.isTraceEnabled()) {
							logger.trace("Creating interface proxy for FactoryBean '" + beanName + "' of type [" +
									clazz.getName() + "] for use within another @Bean method because its " +
									(finalClass ? "implementation class" : "getObject() method") +
									" is final: Otherwise a getObject() call would not be routed to the factory.");
						}
						// 代码七:通过FactoryBean创建接口类型的代理
						return createInterfaceProxyForFactoryBean(factoryBean, exposedType, beanFactory, beanName);
					}
					else {
						// 打印日志,final类型的类或final无法进行代理
						if (logger.isDebugEnabled()) {
							logger.debug("Unable to proxy FactoryBean '" + beanName + "' of type [" +
									clazz.getName() + "] for use within another @Bean method because its " +
									(finalClass ? "implementation class" : "getObject() method") +
									" is final: A getObject() call will NOT be routed to the factory. " +
									"Consider declaring the return type as a FactoryBean interface.");
						}
						return factoryBean;
					}
				}
			}
			catch (NoSuchMethodException ex) {
				// No getObject() method -> shouldn't happen, but as long as nobody is trying to call it...
			}

			// 代码八:通过FactoryBean创建CGLIB类型的代理
			return createCglibProxyForFactoryBean(factoryBean, beanFactory, beanName);
		}

(2) 代码七:createInterfaceProxyForFactoryBean(),通过JDK动态代理完成增强。

// 通过FactoryBean创建接口类型的代理
		private Object createInterfaceProxyForFactoryBean(final Object factoryBean, Class<?> interfaceType,
				final ConfigurableBeanFactory beanFactory, final String beanName) {

			//通过JDK动态代理实现对目标接口的增强
			return Proxy.newProxyInstance(
					factoryBean.getClass().getClassLoader(), new Class<?>[] {interfaceType},
					(proxy, method, args) -> {
						if (method.getName().equals("getObject") && args == null) {
							return beanFactory.getBean(beanName);
						}
						return ReflectionUtils.invokeMethod(method, factoryBean, args);
					});
		}

(3)代码块八:createCglibProxyForFactoryBean(),通过CGLIB代理完成增强。

private Object createCglibProxyForFactoryBean(final Object factoryBean,
				final ConfigurableBeanFactory beanFactory, final String beanName) {

			// 创建CGLIB增强器
			Enhancer enhancer = new Enhancer();
			enhancer.setSuperclass(factoryBean.getClass());
			enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
			enhancer.setCallbackType(MethodInterceptor.class);

			// Ideally create enhanced FactoryBean proxy without constructor side effects,
			// analogous to AOP proxy creation in ObjenesisCglibAopProxy...
			Class<?> fbClass = enhancer.createClass();
			Object fbProxy = null;


			// SpringObjenesis
			// spring特定变体,提供基于{@code Class}键而不是类名的缓存;
			// 就是通过Class可以获取对应的缓存实例
			// 从objenesis缓存获取对象
			if (objenesis.isWorthTrying()) {
				try {
					fbProxy = objenesis.newInstance(fbClass, enhancer.getUseCache());
				}
				catch (ObjenesisException ex) {
					logger.debug("Unable to instantiate enhanced FactoryBean using Objenesis, " +
							"falling back to regular construction", ex);
				}
			}

			if (fbProxy == null) {
				try {
					// 通过无参构造器创建对象
					fbProxy = ReflectionUtils.accessibleConstructor(fbClass).newInstance();
				}
				catch (Throwable ex) {
					throw new IllegalStateException("Unable to instantiate enhanced FactoryBean using Objenesis, " +
							"and regular FactoryBean instantiation via default constructor fails as well", ex);
				}
			}

			((Factory) fbProxy).setCallback(0, (MethodInterceptor) (obj, method, args, proxy) -> {
				if (method.getName().equals("getObject") && args.length == 0) {
					return beanFactory.getBean(beanName);
				}
				return proxy.invoke(factoryBean, args);
			});

			return fbProxy;
		}

(4)代码块九:isCurrentlyInvokedFactoryMethod(),当前创建Bean的FactoryMethod与实际调用的方法是否一致。

       我们需要明白什么时候会执行@Bean标记的方法?

        在实例对象的时候,@Bean标记的方法是被作为FactoryMethod创建实例的一种。最终都是会调用SimpleInstantiationStrategy的实例化方法instantiate()进行对象的实例化,

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
……
if (mbd.getFactoryMethodName() != null) {
			// 实例化对象的工厂方法也存在重载的情况,推断工厂方法的逻辑与推断构造器的逻辑类似
			return instantiateUsingFactoryMethod(beanName, mbd, args);
		}
……
}

          而SimpleInstantiationStrategy类维护了一个线程本地变量currentlyInvokedFactoryMethod,用来存储当前线程执行的FactoryMethod,实例化方法instantiate()中会给这个变量设置值。

public class SimpleInstantiationStrategy implements InstantiationStrategy {

	
//当前线程执行的FactoryMethod
private static final ThreadLocal<Method> currentlyInvokedFactoryMethod = new ThreadLocal<>();


@Override
	public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
			@Nullable Object factoryBean, final Method factoryMethod, Object... args) {
     
    // 设置线程本地变量值
    currentlyInvokedFactoryMethod.set(factoryMethod);
	Object result = factoryMethod.invoke(factoryBean, args);
	if (result == null) {
	    result = new NullBean();
	}
    return result;
   }

}

        比较当前调用方法与线程本地变量存储的factoryMethod的方法名称及形参列表(形参个数及形参类型都一致) 是否一致。

// 判断method与当前的FactoryMethod是否相同
		private boolean isCurrentlyInvokedFactoryMethod(Method method) {
			// 当前创建bean对应的方法(@Bean标记的方法名会被作为FactoryMethod保存在缓存中)
			Method currentlyInvoked = SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod();
			// 方法名和参数列表(个数和参数类型)相同
			return (currentlyInvoked != null && method.getName().equals(currentlyInvoked.getName()) &&
					Arrays.equals(method.getParameterTypes(), currentlyInvoked.getParameterTypes()));
		}

        如果一致,使用CGLIB代理,就会执行父类方法。 

(5)代码块十:resolveBeanReference(),解决对象引用。

        当前创建bean的方法与实际调用的方法不一致时,会进入这个方法,我们看到,这里获取beanName对应的实例是通过getBean(),而不是调用实例化方法instantiate(),所以不会多次实例化。

        这个方法大概总结为:

        1)判断当前对象beanName是否正在创建,如果是,临时设置创建中的状态为 false,以避免异常。

        2)获取方法参数数组,如果方法参数数组中有一个值为null,舍弃参数,因为初始化或获取对应的实例时,不运行构造参数模棱两可。

        3)如果是参数不满足要求,获取(或创建,看容器中是否存在)无参实例。满足要求则获取(或创建,看容器中是否存在)有参实例。

        4)如果获取的实例beanInstance不为null,但方法返回值类型与实例类型不匹配,抛出异常(IllegalStateException)。

        5)获取线程本地变量存储的factoryMethod,设置当前实例beanInstance对应的beanName与其的依赖关系。返回beanInstance。(相对于beanInstance是factoryMethod对应的bean的一个属性。)

        6)设置创建中的状态的值。

private Object resolveBeanReference(Method beanMethod, Object[] beanMethodArgs,
				ConfigurableBeanFactory beanFactory, String beanName) {

			// The user (i.e. not the factory) is requesting this bean through a call to
			// the bean method, direct or indirect. The bean may have already been marked
			// as 'in creation' in certain autowiring scenarios; if so, temporarily set
			// the in-creation status to false in order to avoid an exception.
			// 是否正在创建,false
			boolean alreadyInCreation = beanFactory.isCurrentlyInCreation(beanName);
			try {
				if (alreadyInCreation) {
					beanFactory.setCurrentlyInCreation(beanName, false);
				}
				boolean useArgs = !ObjectUtils.isEmpty(beanMethodArgs);
				// 参数不为空且是单例对象
				if (useArgs && beanFactory.isSingleton(beanName)) {
					// Stubbed null arguments just for reference purposes,
					// expecting them to be autowired for regular singleton references?
					// A safe assumption since @Bean singleton arguments cannot be optional...
					for (Object arg : beanMethodArgs) {
						if (arg == null) {
							useArgs = false;
							break;
						}
					}
				}
				//不是直接调用父类方法(new),而是通过beanFactory.getBean(beanName)
				// 要不要传参,如果beanMethodArgs包含有null值,调用无参的方法获取bean
				// 为什么不会实例化多次的原因,先去从容器中获取
				Object beanInstance = (useArgs ? beanFactory.getBean(beanName, beanMethodArgs) :
						beanFactory.getBean(beanName));
				if (!ClassUtils.isAssignableValue(beanMethod.getReturnType(), beanInstance)) {
					// Detect package-protected NullBean instance through equals(null) check
					if (beanInstance.equals(null)) {
						if (logger.isDebugEnabled()) {
							logger.debug(String.format("@Bean method %s.%s called as bean reference " +
									"for type [%s] returned null bean; resolving to null value.",
									beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName(),
									beanMethod.getReturnType().getName()));
						}
						beanInstance = null;
					}
					else {
						String msg = String.format("@Bean method %s.%s called as bean reference " +
								"for type [%s] but overridden by non-compatible bean instance of type [%s].",
								beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName(),
								beanMethod.getReturnType().getName(), beanInstance.getClass().getName());
						try {
							BeanDefinition beanDefinition = beanFactory.getMergedBeanDefinition(beanName);
							msg += " Overriding bean of same name declared in: " + beanDefinition.getResourceDescription();
						}
						catch (NoSuchBeanDefinitionException ex) {
							// Ignore - simply no detailed message then.
						}
						throw new IllegalStateException(msg);
					}
				}
				Method currentlyInvoked = SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod();
				if (currentlyInvoked != null) {
					// 默认为方法名,如果自定义了name,使用自定义的name,如果自定义了多个name,取下标为0的那个作为name
					String outerBeanName = BeanAnnotationHelper.determineBeanNameFor(currentlyInvoked);
					// 维护依赖关系集合,beanName需要被添加到哪些bean(dependentBeanMap),outerBeanName需要哪些依赖(dependenciesForBean)
					beanFactory.registerDependentBean(beanName, outerBeanName);
				}
				return beanInstance;
			}
			finally {
                // false
				if (alreadyInCreation) {
					// 设置为正在创建
					beanFactory.setCurrentlyInCreation(beanName, true);
				}
			}
		}

(6)BeanFactoryAwareMethodInterceptor实现的方法增强。

        如果方法名称为setBeanFactory()且返回值类型为BeanFactoryAware.class,直接调用父类的setBeanFactory()方法,不进行任何增强。

private static class BeanFactoryAwareMethodInterceptor implements MethodInterceptor, ConditionalCallback {

		@Override
		@Nullable
		public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
			// 根据class类型和name查找field
			Field field = ReflectionUtils.findField(obj.getClass(), BEAN_FACTORY_FIELD);
			Assert.state(field != null, "Unable to find generated BeanFactory field");
			field.set(obj, args[0]);

			// Does the actual (non-CGLIB) superclass implement BeanFactoryAware?
			// If so, call its setBeanFactory() method. If not, just exit.
			if (BeanFactoryAware.class.isAssignableFrom(ClassUtils.getUserClass(obj.getClass().getSuperclass()))) {
				//调用BeanFactoryAware.setBeanFactory()
				return proxy.invokeSuper(obj, args);
			}
			return null;
		}

}

 (7)代码分析

        看完源码,我们对如下代码进行分析。

@Configuration
public class SpringProxy {


	@Bean
	public A a(){
		System.out.println("init A");
		return new A();
	}


	@Bean
	public B b(){
		a();
		System.out.println("init B");
		return new B();
	}

}

        1)A对象实例化时,通过工厂方法实例化 A对象,把当前线程本地变量currentlyInvokedFactoryMethod赋值为a(),进入a()方法,判断当前调用方法(a())是否与线程本地变量存储的factoryMethod一致,一致,执行CGLIB代理,就会调用父类方法进行实例化。(new A())。

        2)B对象实例化时,通过工厂方法实例化 B对象,把当前线程本地变量currentlyInvokedFactoryMethod赋值为b(),进入b()方法,判断当前调用方法(b())是否与线程本地变量存储的factoryMethod一致,一致,执行CGLIB代理,就会调用父类方法进行实例化。(a())。

        3)B对象实例化调用父类方法时,会执行a()方法,判断当前调用方法(a())是否与线程本地变量存储的factoryMethod(b())一致,不一致,获取方法名和方法参数,通过getBean()获取方法对应的实例对象beanInstance,并把该实例作为当前线程本地变量存储的factoryMethod(b())对应的bean的一个依赖,并进行维护依赖关系相关集合。返回获取的beanInstance。

        4)a()返回后,继续执行(b())父类的方法(new B()),完成B对象的实例化。

四、总结 

        我们知道java类实例化的基本流程是先将.java文件编译成.class文件,然后通过类加载器加载class文件到jvm中,jvm将class解析成字节码(byte)。而动态代理则是直接生成对应的字节码(byte),在需要创建大量类的系统中,使用动态代理可以防止类爆炸。

        通过前面的源码阅读,@Configuration注解标识的类会使用代理,可以保证生成的对象是单例的,我们在开发中可以好好利用这个特性。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值