基于Spring auto-proxy 和基于 AspectJ pointcuts的实现

LD is tigger forever,CG are not brothers forever, throw the pot and shine forever.
Modesty is not false, solid is not naive, treacherous but not deceitful, stay with good people, and stay away from poor people.
talk is cheap, show others the code,Keep progress,make a better result.
Survive during the day and develop at night。

目录

概述

cglib 动态代理的源码分析
@Component
public class TestAopTarget {

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

自定义的MethodInterceptor:

public class MyMethodIncerceptor implements MethodInterceptor {

    /*
       Object o:要增强的目标对象
       Method method:拦截的方法
       Object[] objects:参数列表
       MethodProxy:对方法的代理
     */
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("_____before");
        Object result = methodProxy.invokeSuper(o, objects);
        System.out.println("_____after");
        return result;

    }
}

测试类:
CgLib中AOP的实现是基于org.springframework.cglib.proxy包中Enhancer和MethodInterceptor(是CgLib包中的,不是AOP alliance中的同名接口)两个接口来实现的。
对于整个过程,我们可以概括为:
定义自定义的MethodInterceptor(其实现的intercept方法中是AOP具体的逻辑)
创建Enhance、设置Callback为上述MethodInterceptor
enhancer.create()创建代理

Spring框架中cglib 代理源码分析
在得到Advisors之后,通过proxyFactory.getProxy获取代理

public Object getProxy(ClassLoader classLoader) {
		return createAopProxy().getProxy(classLoader);
	}

假定createAopProxy中决定的实现类为ObjenesisCglibAopProxy
这次我们从getProxy开始看起

getProxy获取代理:
此方法是在ObjenesisCglibAopProxy的父类CglibAopProxy中实现的

@Override
	public Object getProxy(ClassLoader classLoader) {
		if (logger.isDebugEnabled()) {
			logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
		}

		try {
			Class<?> rootClass = this.advised.getTargetClass();
			Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

			Class<?> proxySuperClass = rootClass;
			if (ClassUtils.isCglibProxyClass(rootClass)) {
				proxySuperClass = rootClass.getSuperclass();
				Class<?>[] additionalInterfaces = rootClass.getInterfaces();
				for (Class<?> additionalInterface : additionalInterfaces) {
					this.advised.addInterface(additionalInterface);
				}
			}

			// Validate the class, writing log messages as necessary.
			validateClassIfNecessary(proxySuperClass, classLoader);

			// Configure CGLIB Enhancer...
			Enhancer 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 ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));

			Callback[] 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 above
			enhancer.setCallbackFilter(new ProxyCallbackFilter(
					this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
			enhancer.setCallbackTypes(types);

			// Generate the proxy class and create a proxy instance.
			return createProxyClassAndInstance(enhancer, callbacks);
		}
		catch (CodeGenerationException ex) {
			throw new AopConfigException("Could not generate CGLIB subclass of class [" +
					this.advised.getTargetClass() + "]: " +
					"Common causes of this problem include using a final class or a non-visible class",
					ex);
		}
		catch (IllegalArgumentException ex) {
			throw new AopConfigException("Could not generate CGLIB subclass of class [" +
					this.advised.getTargetClass() + "]: " +
					"Common causes of this problem include using a final class or a non-visible class",
					ex);
		}
		catch (Exception ex) {
			// TargetSource.getTarget() failed
			throw new AopConfigException("Unexpected AOP exception", ex);
		}
	}

方法包含的步骤:
获取目标类的全部接口
检查目标类中是否含有final修饰的方法

Enhancer enhancer = createEnhancer();

获取拦截器链Callback
Callback[] callbacks = getCallbacks(rootClass);

生成代理类并创建代理(设置enhance的callback数值)

return createProxyClassAndInstance(enhancer, callbacks)

这个过程中已经实现了我们上述总结的三个步骤:
定义自定义的MethodInterceptor(其实现的intercept方法中是AOP具体的逻辑)
创建Enhance、设置Callback为上述MethodInterceptor
enhancer.create()创建代理
需要关注的过程:
getCallbacks获取拦截器链
createProxyClassAndInstance获取代理

重点在第1步:创建DynamicAdvisedInterceptor
DynamicAdvisedInterceptor类实现了MethodIntercepto
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable
那么其中一定会有intercept方法的实现,就是AOP具体的逻辑:

@Override
		public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
			Object oldProxy = null;
			boolean setProxyContext = false;
			Class<?> targetClass = null;
			Object target = null;
			try {
				if (this.advised.exposeProxy) {
					// Make invocation available if necessary.
					oldProxy = AopContext.setCurrentProxy(proxy);
					setProxyContext = true;
				}
				// May be null. Get as late as possible to minimize the time we
				// "own" the target, in case it comes from a pool...
				target = getTarget();
				if (target != null) {
					targetClass = target.getClass();
				}
				List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
				Object retVal;
				// Check whether we only have one InvokerInterceptor: that is,
				// no real advice, but just reflective invocation of the target.
				if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
					// We can skip creating a MethodInvocation: just invoke the target directly.
					// Note that the final invoker must be an InvokerInterceptor, so we know
					// it does nothing but a reflective operation on the target, and no hot
					// swapping or fancy proxying.
					Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
					retVal = methodProxy.invoke(target, argsToUse);
				}
				else {
					// We need to create a method invocation...
					retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
				}
				retVal = processReturnType(proxy, target, method, retVal);
				return retVal;
			}
			finally {
				if (target != null) {
					releaseTarget(target);
				}
				if (setProxyContext) {
					// Restore old proxy.
					AopContext.setCurrentProxy(oldProxy);
				}
			}
		}

1.1.1 intercept()中:获取的MethodInterceptor拦截器连(AOP aliliance 中的接口)
1.2.1通过Advisors中的Advice获取(包装为)MethodInterceptor拦截器链(AOP alliance中的接口) ,描述了如何根据Advice获取MethodInterceptor。
1.1.2 intercept()中创建一个MethodInvalication 并调用proceed()
retVal =
new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy)
.proceed();
CglibMethodInvocation类继承了ReflectiveMethodInvocation,可见它也是实现了AOP联盟中的MethodInvocation接口

private static class CglibMethodInvocation extends ReflectiveMethodInvocation

1.311.3 返回此MethodInvocation
2. createProxyClassAndInstance获取代理

protected 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 {
				proxyInstance = (this.constructorArgs != null ?
						proxyClass.getConstructor(this.constructorArgTypes).newInstance(this.constructorArgs) :
						proxyClass.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;
	}

方法中做了2件事情:
通过Enhancer创建代理实例
将实例设置回调:传入的callback参数

JDK 动态代理源码分析

1.创建项目接口
在项目的 src 目录下创建一个名为 com.mengma.dao 的包,在该包下创建一个 CustomerDao 接口,编辑后如下所示。

public interface CustomerDao {
    public void add(); // 添加

    public void update(); // 修改

    public void delete(); // 删除

    public void find(); // 查询
}

创建实现类,创建实现类 CustomerDaoImpl

package com.mengma.dao;

public class CustomerDaoImpl implements CustomerDao {

    @Override
    public void add() {
        System.out.println("添加客户...");
    }

    @Override
    public void update() {
        System.out.println("修改客户...");
    }

    @Override
    public void delete() {
        System.out.println("删除客户...");
    }

    @Override
    public void find() {
        System.out.println("修改客户...");
    }
}
  1. 创建切面类 MyAspect

public class MyAspect {
    public void myBefore() {
        System.out.println("方法执行之前");
    }

    public void myAfter() {
        System.out.println("方法执行之后");
    }
}

在切面中定义了两个增强的方法,分别为 myBefore() 方法和 myAfter() 方法,用于对目标类(CustomerDaoImpl)进行增强。
MyBeanFactory ,在该类中使用 java.lang.reflect.Proxy 实现 JDK 动态代理

5.创建代理类MyBeanFactory
在该类中使用 java.lang.reflect.Proxy 实现 JDK 动态代理

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import com.mengma.dao.CustomerDao;
import com.mengma.dao.CustomerDaoImpl;

public class MyBeanFactory {

    public static CustomerDao getBean() {
        // 准备目标类
        final CustomerDao customerDao = new CustomerDaoImpl();
        // 创建切面类实例
        final MyAspect myAspect = new MyAspect();
        // 使用代理类,进行增强
        return (CustomerDao) Proxy.newProxyInstance(
                MyBeanFactory.class.getClassLoader(),
                new Class[] { CustomerDao.class }, new InvocationHandler() {
                    public Object invoke(Object proxy, Method method,
                            Object[] args) throws Throwable {
                        myAspect.myBefore(); // 前增强
                        Object obj = method.invoke(customerDao, args);
                        myAspect.myAfter(); // 后增强
                        return obj;
                    }
                });
    }
}

6.创建测试类JDKProxyTest

public class JDKProxyTest {
    @Test
    public void test() {
        // 从工厂获得指定的内容(相当于spring获得,但此内容时代理对象)
        CustomerDao customerDao = MyBeanFactory.getBean();
        // 执行方法
        customerDao.add();
        customerDao.update();
        customerDao.delete();
        customerDao.find();
    }
}

问题

实现思路分析

相关工具如下:

分析:

小结:

主要讲述了注解配置方式的Mybatis数据库源源码分析原理剖析, 里面有许多不足,请大家指正~

参考资料和推荐阅读

1.链接: 参考资料.
2.链接: 参考资料.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

执于代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值