基于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("修改客户...");
}
}
- 创建切面类 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数据库源源码分析原理剖析, 里面有许多不足,请大家指正~