一、前言
在上一节中我们已经介绍了在createBean过程中去执行AspectJAutoProxyCreator的after方法,然后去获取当前bean适配的advisor,如果还不熟悉的可以去看下之前的博客,接下来我们分析Spring AOP是如何创建代理对象的,在此之前如果对于JDK动态代理以及cglib源码不熟悉的也先去看一下之前对于这两个代理的源码分析博客。Spring源码解析(24)之JDK动态代理与cglib动态代理源码解析_spring 选择 jdk 代理 cglib 代理源码-CSDN博客
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {// 如果已经处理过,直接返回if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {return bean;}// 这里advisedBeans缓存了已经进行了代理的bean,如果缓存中存在,则可以直接返回if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {return bean;}// 这里isInfrastructureClass()用于判断当前bean是否为Spring系统自带的bean,自带的bean是// 不用进行代理的;shouldSkip()则用于判断当前bean是否应该被略过if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {// 对当前bean进行缓存this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean;}// Create proxy if we have advice.// 获取当前bean的Advices和AdvisorsObject[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);// 对当前bean的代理状态进行缓存if (specificInterceptors != DO_NOT_PROXY) {// 对当前bean的代理状态进行缓存this.advisedBeans.put(cacheKey, Boolean.TRUE);// 根据获取到的Advices和Advisors为当前bean生成代理对象Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));// 缓存生成的代理bean的类型,并且返回生成的代理beanthis.proxyTypes.put(cacheKey, proxy.getClass());return proxy;}this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean;}
二、源码分析
接下来我们继续分析createProxy方法,来看下Spring AOP是如何创建代理对象的。
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,@Nullable Object[] specificInterceptors, TargetSource targetSource) {// 给bean定义设置暴露属性if (this.beanFactory instanceof ConfigurableListableBeanFactory) {AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);}// 创建代理工厂ProxyFactory proxyFactory = new ProxyFactory();// 获取当前类中相关属性proxyFactory.copyFrom(this);// 决定对于给定的bean是否应该使用targetClass而不是他的接口代理,检查proxyTargetClass设置以及preserverTargetClass属性if (!proxyFactory.isProxyTargetClass()) {// 判断是 使用jdk动态代理 还是cglib代理if (shouldProxyTargetClass(beanClass, beanName)) {proxyFactory.setProxyTargetClass(true);}else {// 添加代理接口evaluateProxyInterfaces(beanClass, proxyFactory);}}// 构建增强器Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);proxyFactory.addAdvisors(advisors);// 设置到要代理的类proxyFactory.setTargetSource(targetSource);// 定制代理customizeProxyFactory(proxyFactory);// 控制代理工程被配置之后,是否还允许修改通知,默认值是falseproxyFactory.setFrozen(this.freezeProxy);if (advisorsPreFiltered()) {proxyFactory.setPreFiltered(true);}// 真正创建代理对象return proxyFactory.getProxy(getProxyClassLoader());}
设置一系列属性,然后判断是否有proxyTargetClass来决定是使用cglib代理还是JDK代理。
public Object getProxy(@Nullable ClassLoader classLoader) {// createAopProxy() 用来创建我们的代理工厂return createAopProxy().getProxy(classLoader);}
首先会在createAopProxy中判断是使用cglib代理还是jdk动态代理。
protected final synchronized AopProxy createAopProxy() {if (!this.active) {// 监听调用AdvisedSupportListener实现类的activated方法activate();}// 通过AopProxyFactory获得AopProxy,这个AopProxyFactory是在初始化函数中定义的,使用的是DefaultAopProxyFactoryreturn getAopProxyFactory().createAopProxy(this);}public AopProxyFactory getAopProxyFactory() {return this.aopProxyFactory;}/*** Create a new ProxyCreatorSupport instance.*/public ProxyCreatorSupport() {this.aopProxyFactory = new DefaultAopProxyFactory();}
所以最终会调到DefaultAopProxyFactory中去判断,继续往下跟。
@Overridepublic AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {// 这段代码用来判断选择哪种创建代理对象的方式// config.isOptimize() 是否对代理类的生成使用策略优化 其作用是和isProxyTargetClass是一样的 默认为false// config.isProxyTargetClass() 是否使用Cglib的方式创建代理对象 默认为false// hasNoUserSuppliedProxyInterfaces目标类是否有接口存在 且只有一个接口的时候接口类型不是SpringProxy类型if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {// 上面的三个方法有一个为true的话,则进入到这里// 从AdvisedSupport中获取目标类 类对象Class<?> targetClass = config.getTargetClass();if (targetClass == null) {throw new AopConfigException("TargetSource cannot determine target class: " +"Either an interface or a target is required for proxy creation.");}// 判断目标类是否是接口 如果目标类是接口的话,则还是使用JDK的方式生成代理对象// 如果目标类是Proxy类型 则还是使用JDK的方式生成代理对象if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {return new JdkDynamicAopProxy(config);}// 配置了使用Cglib进行动态代理或者目标类没有接口,那么使用Cglib的方式创建代理对象return new ObjenesisCglibAopProxy(config);}else {// 使用JDK的提供的代理方式生成代理对象return new JdkDynamicAopProxy(config);}}
上面就能够判断得到是使用cglib动态还是还是jdk动态代理,如果使用的是cglib动态代理则返回ObjenesisCglibAopProxy,否则则返回JkdDynamicAopProxy对象。
我们继续往下跟getProxy方法,看他是如果创建代理对象的。
@Overridepublic Object getProxy(@Nullable ClassLoader classLoader) {if (logger.isTraceEnabled()) {logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());}try {// 从advised中获取ioc容器中配置的target对象Class<?> rootClass = this.advised.getTargetClass();Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");Class<?> proxySuperClass = rootClass;//如果目标对象已经是CGLIB 生成代理对象(就是比较类名称中有 $$ 字符串),那么就取目标对象的父类作为目标对象的类if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {proxySuperClass = rootClass.getSuperclass();// 获取原始父类的接口Class<?>[] additionalInterfaces = rootClass.getInterfaces();for (Class<?> additionalInterface : additionalInterfaces) {this.advised.addInterface(additionalInterface);}}// Validate the class, writing log messages as necessary.// 打印出不能代理的方法名,CGLIB 是使用继承实现的,所以final , static 的方法不能被增强validateClassIfNecessary(proxySuperClass, classLoader);// Configure CGLIB Enhancer...// 创建及配置EnhancerEnhancer enhancer = createEnhancer();if (classLoader != null) {enhancer.setClassLoader(classLoader);if (classLoader instanceof SmartClassLoader &&((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {enhancer.setUseCache(false);}}// 配置超类,代理类实现的接口,回调方法等enhancer.setSuperclass(proxySuperClass);enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));// 获取callbacksCallback[] callbacks = getCallbacks(rootClass);Class<?>[] types = new Class<?>[callbacks.length];for (int x = 0; x < types.length; x++) {types[x] = callbacks[x].getClass();}// fixedInterceptorMap only populated at this point, after getCallbacks call aboveenhancer.setCallbackFilter(new ProxyCallbackFilter(this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));enhancer.setCallbackTypes(types);// Generate the proxy class and create a proxy instance.// 通过 Enhancer 生成代理对象,并设置回调return createProxyClassAndInstance(enhancer, callbacks);}catch (CodeGenerationException | IllegalArgumentException ex) {throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +": Common causes of this problem include using a final class or a non-visible class",ex);}catch (Throwable ex) {// TargetSource.getTarget() failedthrow new AopConfigException("Unexpected AOP exception", ex);}}
首先看一下AopProxyUtils.completeProxiedInterfaces(this.advised)。
这个方法会给我们的代理类加上两个接口,一个是SpringProxy,是一个advised对象,我们之前了解过advisor对象是一个通知器,他里面包含有advice和pointcut对象,而advice对象就是具体的某一个消息通知,那么advised是干啥的?我们来看下他的方法以及他是在那里生成的。
其实他就是ProxyFactory对象,就是用来配置代理的,那么他是在哪里赋值的呢?我们回到我们判断是使用哪种代理方式那里。
而我们的ProxyFactory就是继承ProxyCreatorSupport的。
然后看一下他是如何设置我们的回调方法的,继续往下跟 getCallbacks方法。
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {// Parameters used for optimization choices...// 对于expose-proxy属性的处理,是否暴露当前对象为ThreadLocal模式,在当前上下文中能够进行引用boolean exposeProxy = this.advised.isExposeProxy();boolean isFrozen = this.advised.isFrozen();boolean isStatic = this.advised.getTargetSource().isStatic();// Choose an "aop" interceptor (used for AOP calls).// 将拦截器封装在DynamicAdvisedInterceptor中Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);// Choose a "straight to target" interceptor. (used for calls that are// unadvised but can return this). May be required to expose the proxy.Callback targetInterceptor;if (exposeProxy) {targetInterceptor = (isStatic ?new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));}else {targetInterceptor = (isStatic ?new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));}// Choose a "direct to target" dispatcher (used for// unadvised calls to static targets that cannot return this).Callback targetDispatcher = (isStatic ?new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());Callback[] mainCallbacks = new Callback[] {// 将拦截器链加入Callback中aopInterceptor, // for normal advicetargetInterceptor, // invoke target without considering advice, if optimizednew SerializableNoOp(), // no override for methods mapped to thistargetDispatcher, this.advisedDispatcher,new EqualsInterceptor(this.advised),new HashCodeInterceptor(this.advised)};Callback[] callbacks;// If the target is a static one and the advice chain is frozen,// then we can make some optimizations by sending the AOP calls// direct to the target using the fixed chain for that method.if (isStatic && isFrozen) {Method[] methods = rootClass.getMethods();Callback[] fixedCallbacks = new Callback[methods.length];this.fixedInterceptorMap = new HashMap<>(methods.length);// TODO: small memory optimization here (can skip creation for methods with no advice)for (int x = 0; x < methods.length; x++) {Method method = methods[x];List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass);fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());this.fixedInterceptorMap.put(method, x);}// Now copy both the callbacks from mainCallbacks// and fixedCallbacks into the callbacks array.callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);this.fixedInterceptorOffset = mainCallbacks.length;}else {callbacks = mainCallbacks;}return callbacks;}
最后他封装了这些回调方法。第一个Callback是DynamicAdvisorInterceptor.
然后就会调具体的createProxyClassAndInstance来创建代理对象了,继续往下跟。
@Overrideprotected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {Class<?> proxyClass = enhancer.createClass();Object proxyInstance = null;if (objenesis.isWorthTrying()) {try {proxyInstance = objenesis.newInstance(proxyClass, enhancer.getUseCache());}catch (Throwable ex) {logger.debug("Unable to instantiate proxy using Objenesis, " +"falling back to regular proxy construction", ex);}}if (proxyInstance == null) {// Regular instantiation via default constructor...try {Constructor<?> ctor = (this.constructorArgs != null ?proxyClass.getDeclaredConstructor(this.constructorArgTypes) :proxyClass.getDeclaredConstructor());ReflectionUtils.makeAccessible(ctor);proxyInstance = (this.constructorArgs != null ?ctor.newInstance(this.constructorArgs) : ctor.newInstance());}catch (Throwable ex) {throw new AopConfigException("Unable to instantiate proxy using Objenesis, " +"and regular proxy instantiation via default constructor fails as well", ex);}}((Factory) proxyInstance).setCallbacks(callbacks);return proxyInstance;}public Class createClass() {classOnly = true;return (Class) createHelper();}private Object createHelper() {// 校验callbackTypes、filter是否为空,以及为空时的处理preValidate();// 通过newInstance方法来创建EnhancerKey对象,正常情况下,只需要new一个对象就可以调用方法了,但是Key_Factory是一个EnhancerKey类型,是一个内部接口,需要动态代理来实现,最终是为了调用newInstance方法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);// 设置当前enhancer的代理类的key标识this.currentKey = key;// 调用父类即AbstractClassGenerator的创建代理类Object result = super.create(key);return result;
最后就会返回一个创建好的代理对象.
然后回到我们获取得到这个代理对象,然后调用对应的代理方法,这时候会怎么去执行呢?很明显因为我们第一个放入的是DynamicAdvisorInterceptor对象,所以第一个就会进入到这个拦截器中。
public static void main(String[] args) throws Exception {
// saveGeneratedCGlibProxyFiles(System.getProperty("user.dir")+"/proxy");ApplicationContext ac = new ClassPathXmlApplicationContext("aop.xml");MyCalculator bean = ac.getBean(MyCalculator.class);System.out.println(bean.toString());bean.add(1,1);bean.sub(1,1);}
这里想一下,我们有这么多通知切面,他是如何去判断这些通知的执行顺序 。
在spring他是通过一个责任链模式来组装一个链式结构,不知道还是否继续要之前获取当前bean适配的advisor后会给所有的advisor集合中添加一个exposeInvocationInterceptor对象,是通过这个对象来判断当前执行的是哪个advisor对象,这个具体会在下一节中具体介绍。