xiaobaoqiu Blog

Think More, Code Less

从代理到Spring事务1-代理

最近再项目中发现不少同事(包括自己)不太理解默认情况下的Spring事务的运行机制(主要是不理解AOP机制),导致随意使用事务注解.因此也在很多场景事务不生效。因此想从代理机制开始理一下整个Spring声明式事务的原理。

因为篇幅太长,分成三个部分:

(1).代理
(2).Spring的AOP
(3).Spring的事务

1.代理

通常,我们代码中处理核心的业务逻辑,还包含一些枝节性的代码和功能,比如日志记录、消息发送、安全、事务保证和监控等。

我们通常期望将这些枝节性的代码功能和我们的核心业务逻辑分离,减少业务功能和枝节功能的耦合。这时候我们就要使用代理来达到我们的目的。

代理的作用是:为其它对象提供一种代理以控制对这个对象的访问。简单理解就是中间的作用。代理一般涉及到三个角色:

(1).抽象角色:声明真实对象和代理对象的共同接口;
(2).代理角色:代理对象内部包含有真实角色的引用,从而可以操作真实角色,同时代理对象与真实对象有相同的接口,能在任何时候代替真实对象,同时代理对象可以在执行真实对 象前后加入特定的逻辑以实现功能的扩展;
(3).真实角色:代理角色所代表的真实对象,是我们最终要引用的对象;

1.1 代理模式

代理模式是一个经典的设计模式,介绍往上很多。

下面是一个最简单的实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public interface IHello {
    void hello();
}

public class HelloImpl implements IHello {
    @Override
    public void hello() {
        System.out.println("HelloImpl: Hello World.");
    }
}

public class HelloProxyImpl implements IHello {

    private IHello inner;

    public HelloProxyImpl(IHello inner) {
        this.inner = inner;
    }

    @Override
    public void hello() {
        doSomethingBefore();
        
        inner.hello();
        
        doSomethingAfter();
    }

    private void doSomethingBefore() {
        System.out.println("HelloProxyImpl: Before hello()...");
    }

    private void doSomethingAfter() {
        System.out.println("HelloProxyImpl: After hello()...");
    }

}

UML图大致如下:

从代码上我们可以看出,代理模式要求(这也是它的限制所在):

(1).代理类需要和被代理者一样实现相同的接口;
(2).代理类包含被代理者的引用;

1.2 Java动态代理

代理模式我们可以理解为一种静态代理,其问题是需要我们显示的为每个需要被代理的类实现一个代理类,即一个代理类只能为i一个被代理者做代理的功能。如果有上千个类需要代理,估计要骂娘了。

java动态代理正是为了解决这个问题。主要通过java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口。我们只需要实现InvocationHandler接口,在实现invoke()方法的时候加上我们的代理逻辑。

一个简单的使用实例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
/**
 * @author xiaobaoqiu  Date: 16-3-10 Time: 下午6:18
 */
public class JavaDynamicProxy implements InvocationHandler {

    /**
     * 被代理者
     */
    private Object inner;

    /**
     * 生成代理类
     */
    public static Object generateProxy(Object inner) {
        return Proxy.newProxyInstance(
                inner.getClass().getClassLoader(),
                inner.getClass().getInterfaces(),
                new JavaDynamicProxy(inner));
    }

    private JavaDynamicProxy(Object inner) {
        this.inner = inner;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        doSomethingBefore();

        Object result = method.invoke(inner, args);

        doSomethingAfter();

        return result;
    }

    private void doSomethingBefore() {
        System.out.println("JavaDynamicProxy: Before...");
    }

    private void doSomethingAfter() {
        System.out.println("JavaDynamicProxy: After...");
    }
}

//使用
public static void main(String[] args) {
        //被动态代理的IHello实例对象A
        IHello helloA = new HelloImpl();
        //生成对象A的动态代理
        IHello helloAProxy = (IHello) JavaDynamicProxy.generateProxy(helloA);
        helloAProxy.hello();

        System.out.println("-------------------------------------------------");
        // 一个JavaDynamicProxy可以一直使用

        //被动态代理的IHello实例对象B
        IHello helloB = new HelloWithLogImpl();
        //生成对象B的动态代理
        IHello helloBProxy = (IHello) JavaDynamicProxy.generateProxy(helloB);
        helloBProxy.hello();

        System.out.println("-------------------------------------------------");
        //被动态代理对象IBye实例
        IBye bye = new ByeImpl();
        //生成IBye实例的动态代理
        IBye byeProxy = (IBye) JavaDynamicProxy.generateProxy(bye);
        byeProxy.bye();
}

JavaDynamicProxy.generateProxy的输出会是一个动态的代理类。debug信息如下,从debug信息我们大致知道,这个代理类的类名称为$Proxy0,内部包含一个属性名为h的属性,h指向的就是我们实现的InvocationHandler的类(这里即JavaDynamicProxy)的实例。

但是Java动态代理的限制是:

(1).被代理的类要求至少实现了一个Interface;
(2).被代理的类要求有public的构造函数(即没有显示的将其设置为private等);
(3).被代理的类要求不是final;

如下代理一个没有实现任何接口的类会报错

1
2
3
4
5
6
    //没有实现任何interface的类使不能被动态代理的
    System.out.println("-------------------------------------------------");
    HelloWithoutInterface helloC = new HelloWithoutInterface();
    //生成对象C的动态代理
    HelloWithoutInterface helloCProxy = (HelloWithoutInterface) JavaDynamicProxy.generateProxy(helloC);
    helloCProxy.hello();

错误信息如下:

1
2
3
4
5
6
7
Exception in thread "main" java.lang.ClassCastException: com.sun.proxy.$Proxy2 cannot be cast to proxy.javaProxy.HelloWithoutInterface
  at proxy.javaProxy.JavaProxyMain.main(JavaProxyMain.java:42)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.lang.reflect.Method.invoke(Method.java:606)
  at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)

Java动态代理的机制是利用反射机制生成。具体代码可以debug,主要的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//Proxy.java
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException {
  ...
  Class<?> cl = getProxyClass0(loader, intfs);  //生成代理类
  ...
  return newInstance(cons, ih);   // 生成代理类的实例
}

private static Class<?> getProxyClass0(ClassLoader loader,  Class<?>... interfaces) {
        //生成代理类的主要逻辑在ProxyClassFactory
        return proxyClassCache.get(loader, interfaces);
}

//ProxyClassFactory的apply方法
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
  ...
            String proxyPkg = null;     // 生成代理类的包路径
            ...
            if (proxyPkg == null) {
                // if no non-public proxy interfaces, use com.sun.proxy package
                proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";   //默认路径在com.sun.proxy下面
            }

            long num = nextUniqueNumber.getAndIncrement();    //代理类的序号, 我们熟悉的$Proxy0中的0
            String proxyName = proxyPkg + proxyClassNamePrefix + num; //代理类的类名称

            //使用ProxyGenerator生成代理类的字节码
            byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces);
            //生成代理类
            return defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length);
}

//ProxyGenerator.generateProxyClass的代码太恶心的...

我们可以自己使用ProxyGenerator来生成代理类并将其字节码记录下来:

1
2
3
// 获取代理类的字节码
byte[] classFile = ProxyGenerator.generateProxyClass("$Proxy0", ByeImpl.class.getInterfaces());
//将字节码写文件,建议写成.class文件

获取的字节码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import proxy.sample.IBye;

public final class $Proxy0 extends Proxy implements IBye {
    private static Method m1;
    private static Method m3;
    private static Method m0;
    private static Method m2;

    public $Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }

    public final boolean equals(Object var1) throws  {
        try {
            return ((Boolean)super.h.invoke(this, m1, new Object[]{var1})).booleanValue();
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final void bye() throws  {
        try {
            super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final int hashCode() throws  {
        try {
            return ((Integer)super.h.invoke(this, m0, (Object[])null)).intValue();
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")});
            m3 = Class.forName("proxy.sample.IBye").getMethod("bye", new Class[0]);
            m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
            m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

从生成的类我们知道,代理类继承Proxy类(这就是为什么Proxy类内的InvocationHandler实例未protected)并实现我们需要的被代理者的Interface(比如这里的bye()方法),另外它只要一个接受一个InvocationHandler为参数的构造函数。当我们调用代理类的bye()方法时候,其实是调用我们实现的InvocationHandler(即上面的JavaDynamicProxy)的invoke()方法,在invoke()方法里面,我们实现了我的代理逻辑。

我们这里这个Demo的大致UML图如下:

参考:http://www.cnblogs.com/cruze/p/3819761.html

1.3 CGLib动态代理

鉴于Java动态代理的限制,我们有需要代理没有任何实现接口的类的时候,可以考虑使用CGLib。CGLib的全称是Code Generate Library。CGLib的使用使用十分广泛,我们这里要讲的Spring AOP,以及EasyMock等。

同样先上Demo代码,我们只需要实现MethodInterceptor接口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
/**
 * @author xiaobaoqiu  Date: 16-3-10 Time: 下午7:15
 */
public class CglibDynamicProxy implements MethodInterceptor {

    /**
     * 动态生成代理类
     */
    public Object generateProxy(Class cls) {
        Enhancer enhancer = new Enhancer();
        enhancer.setCallback(this);
//        enhancer.setCallbackFilter(); //filter
        enhancer.setSuperclass(cls);
        return enhancer.create(); // Enhancer也包含带参数的create方法
    }

    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        doSomethingBefore();

        Object result = proxy.invokeSuper(obj, args);

        doSomethingAfter();

        return result;
    }

    private void doSomethingBefore() {
        System.out.println("CglibDynamicProxy: Before...");
    }

    private void doSomethingAfter() {
        System.out.println("CglibDynamicProxy: After...");
    }
}

//使用
public static void main(String[] args) {
        CglibDynamicProxy proxy = new CglibDynamicProxy();
        //注意: 原始类的instance不需要存在,只需要Class类型

        //用接口IHello接, 或者 HelloImpl 接
        IHello helloAProxy = (IHello)proxy.generateProxy(HelloImpl.class);
        helloAProxy.hello();

        System.out.println("-------------------------------------------------");

        //用接口IHello接, 或者 HelloWithLogImpl 接
        IHello helloBProxy = (IHello)proxy.generateProxy(HelloWithLogImpl.class);
        helloBProxy.hello();

        System.out.println("-------------------------------------------------");

        //代理没有实现任何interface的类
        HelloWithoutInterface helloCProxy = (HelloWithoutInterface)proxy.generateProxy(HelloWithoutInterface.class);
        helloCProxy.hello();
}

同样我们debug一下,得到的信息如下,同样生成了代理类,类名称为proxy.sample.HelloImpl$$EnhancerByCGLIB$$b46b6f06,这个稀奇古怪的类名我们后面会分析:

下面还是尝试分析CGLib动态代理的原理。默认情况下生成的代理class文件只存储在内存中,我们可以在代码中设置一个环境变量:

1
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "/home/xiaobaoqiu/cglib_proxy");

之后我们在目标目录下得到很多的class,其中的proxy目录包含了生成的class文件。我们发现一大堆的class文件,类名都是稀奇古怪:

1
2
3
4
5
xiaobaoqiu@xiaobaoqiu:~/cglib_proxy/proxy/javaProxy$ ll
-rw-rw-r-- 1 xiaobaoqiu xiaobaoqiu 2227  3月 21 18:38 HelloWithoutInterface$$EnhancerByCGLIB$$7d786e36.class
-rw-rw-r-- 1 xiaobaoqiu xiaobaoqiu 5555  3月 21 18:38 HelloWithoutInterface$$EnhancerByCGLIB$$e4e0e0f1.class
-rw-rw-r-- 1 xiaobaoqiu xiaobaoqiu 7744  3月 21 18:38 HelloWithoutInterface$$EnhancerByCGLIB$$e4e0e0f1$$FastClassByCGLIB$$814877d5.class
-rw-rw-r-- 1 xiaobaoqiu xiaobaoqiu 2673  3月 21 18:45 HelloWithoutInterface$$FastClassByCGLIB$$32a767a1.class

我们先看看class文件的生成策略。每个Class Generator(比如这里的Enhancer)都继承自AbstractClassGenerator(实现接口ClassGenerator,这个接口只有一个generateClass的方法),需要实现其generateClass()方法。generateClassName()方法用来生成Class名称:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private String generateClassName(Predicate nameTestPredicate) {
        return namingPolicy.getClassName(namePrefix, source.name, key, nameTestPredicate);
}

//namingPolicy的默认实现NamingPolicy
public String getClassName(String prefix, String source, Object key, Predicate names) {
  //prefix为被代理类的路径,
        String base =
            prefix + "$$" +                       //prefix为被代理类的路径
            source.substring(source.lastIndexOf('.') + 1) +       //获取生成代理类的类,比如我们这里的Enhancer
            getTag() + "$$" +                     //getTag()默认为ByCGLIB
            Integer.toHexString(STRESS_HASH_CODE ? 0 : key.hashCode());   //hashcode
        String attempt = base;
        int index = 2;
        while (names.evaluate(attempt))       //如果有重复,则再在后面加上下标,小标从2开始
            attempt = base + "_" + index++;
        return attempt;
}

下面正式进入class文件的生成原理分析,还是从源代码入手,enhancer.create()最终进入AbstractClassGenerator.create()方法,我们发现最终return的Object是从内部变量obj得来,因此,我们看看ClassLoaderData的生成逻辑:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
protected Object create(Object key) {
            ClassLoader loader = getClassLoader();
            Map<ClassLoader, ClassLoaderData> cache = CACHE;
            ClassLoaderData data = cache.get(loader);
            if (data == null) {
                synchronized (AbstractClassGenerator.class) {
                    data = cache.get(loader);
                    if (data == null) {
                        Map<ClassLoader, ClassLoaderData> newCache = new WeakHashMap<ClassLoader, ClassLoaderData>(cache);
                        data = new ClassLoaderData(classLoader);
                        newCache.put(classLoader, data);
                        CACHE = newCache;
                    }
                }
            }
            this.key = key;
            Object obj = data.get(this);
            if (obj instanceof Class) {
                return firstInstance((Class) obj);
            }
            return nextInstance(obj);
}

public ClassLoaderData(ClassLoader classLoader) {
            this.classLoader = new WeakReference<ClassLoader>(classLoader);
            Function<AbstractClassGenerator, Object> load =
                    new Function<AbstractClassGenerator, Object>() {
                        public Object apply(AbstractClassGenerator gen) {
                            Class klass = gen.generate(ClassLoaderData.this); //生成class的关键代码
                            return gen.wrapCachedClass(klass);
                        }
                    };
            generatedClasses = new LoadingCache<AbstractClassGenerator, Object, Object>(GET_KEY, load);
}

因此我们将目光转到generate()中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
//Enhancer的generate()方法
protected Class generate(ClassLoaderData data) {
        validate();
        if (superclass != null) {
            setNamePrefix(superclass.getName());
        } else if (interfaces != null) {
            setNamePrefix(interfaces[ReflectUtils.findPackageProtected(interfaces)].getName());
        }
        return super.generate(data);  //父类AbstractClassGenerator
}
// AbstractClassGenerator的generate()方法
protected Class generate(ClassLoaderData data) {
            //...
            ClassLoader classLoader = data.getClassLoader();
            this.setClassName(generateClassName(data.getUniqueNamePredicate()));  //代理类的类名称的生成逻辑
            //...
            byte[] b = strategy.generate(this);       //生成策略,默认实现DefaultGeneratorStrategy,生成class文件的字节码
            String className = ClassNameReader.getClassName(new ClassReader(b));
            ProtectionDomain protectionDomain = getProtectionDomain();
            synchronized (classLoader) { // just in case
                if (protectionDomain == null) {
                    gen = ReflectUtils.defineClass(className, b, classLoader);
                } else {
                    gen = ReflectUtils.defineClass(className, b, classLoader, protectionDomain);
                }
            }
            return gen;
            ...//异常处理
}

//DefaultGeneratorStrategy的generate()方法
public byte[] generate(ClassGenerator cg) throws Exception {
        DebuggingClassWriter cw = getClassVisitor();
        transform(cg).generateClass(cw);      //这里调用最终的generateClass()逻辑,Visitor模式
        return transform(cw.toByteArray());   //通过Visitor得到最后的字节码
}

所以最终的调用是Enhancer的generateClass()调用。这代码好晦涩,感觉和JVM加载字节码相关。

看一下CGLib生成的class文件,这个代理类继承了我们的被代理类并且实现了Factory类,类定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
public class HelloWithoutInterface$$EnhancerByCGLIB$$e4e0e0f1 extends proxy.javaProxy.HelloWithoutInterface implements net.sf.cglib.proxy.Factory {
    private boolean CGLIB$BOUND;
    public static java.lang.Object CGLIB$FACTORY_DATA;
    private static final java.lang.ThreadLocal CGLIB$THREAD_CALLBACKS;
    private static final net.sf.cglib.proxy.Callback[] CGLIB$STATIC_CALLBACKS;
    private net.sf.cglib.proxy.MethodInterceptor CGLIB$CALLBACK_0;
    private static final java.lang.reflect.Method CGLIB$hello$0$Method;
    private static final net.sf.cglib.proxy.MethodProxy CGLIB$hello$0$Proxy;
    private static final java.lang.Object[] CGLIB$emptyArgs;
    private static final java.lang.reflect.Method CGLIB$equals$1$Method;
    private static final net.sf.cglib.proxy.MethodProxy CGLIB$equals$1$Proxy;
    private static final java.lang.reflect.Method CGLIB$toString$2$Method;
    private static final net.sf.cglib.proxy.MethodProxy CGLIB$toString$2$Proxy;
    private static final java.lang.reflect.Method CGLIB$hashCode$3$Method;
    private static final net.sf.cglib.proxy.MethodProxy CGLIB$hashCode$3$Proxy;
    private static final java.lang.reflect.Method CGLIB$clone$4$Method;
    private static final net.sf.cglib.proxy.MethodProxy CGLIB$clone$4$Proxy;

    static void CGLIB$STATICHOOK1() { /* compiled code */ }

    final void CGLIB$hello$0() { /* compiled code */ }    //代理的方法

    public final void hello() { /* compiled code */ } //代理的方法

    final boolean CGLIB$equals$1(java.lang.Object o) { /* compiled code */ }

    public final boolean equals(java.lang.Object o) { /* compiled code */ }

    final java.lang.String CGLIB$toString$2() { /* compiled code */ }

    public final java.lang.String toString() { /* compiled code */ }

    final int CGLIB$hashCode$3() { /* compiled code */ }

    public final int hashCode() { /* compiled code */ }

    final java.lang.Object CGLIB$clone$4() throws java.lang.CloneNotSupportedException { /* compiled code */ }

    protected final java.lang.Object clone() throws java.lang.CloneNotSupportedException { /* compiled code */ }

    public static net.sf.cglib.proxy.MethodProxy CGLIB$findMethodProxy(net.sf.cglib.core.Signature signature) { /* compiled code */ }

    public HelloWithoutInterface$$EnhancerByCGLIB$$e4e0e0f1() { /* compiled code */ }

    public static void CGLIB$SET_THREAD_CALLBACKS(net.sf.cglib.proxy.Callback[] callbacks) { /* compiled code */ }

    public static void CGLIB$SET_STATIC_CALLBACKS(net.sf.cglib.proxy.Callback[] callbacks) { /* compiled code */ }

    private static final void CGLIB$BIND_CALLBACKS(java.lang.Object o) { /* compiled code */ }

    public java.lang.Object newInstance(net.sf.cglib.proxy.Callback[] callbacks) { /* compiled code */ }

    public java.lang.Object newInstance(net.sf.cglib.proxy.Callback callback) { /* compiled code */ }

    public java.lang.Object newInstance(java.lang.Class[] classes, java.lang.Object[] objects, net.sf.cglib.proxy.Callback[] callbacks) { /* compiled code */ }

    public net.sf.cglib.proxy.Callback getCallback(int i) { /* compiled code */ }

    public void setCallback(int i, net.sf.cglib.proxy.Callback callback) { /* compiled code */ }

    public net.sf.cglib.proxy.Callback[] getCallbacks() { /* compiled code */ }

    public void setCallbacks(net.sf.cglib.proxy.Callback[] callbacks) { /* compiled code */ }
}

注意,我们生成的动态代理包含两个hello()相关的方法。我们可以使用javap获取其字节码,我们发现和我们被代理者同名的hello()方法是带代理逻辑的,而CGLIB$hello$0()这个则是原始被代理者的直接调用(不包含代理逻辑):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
xiaobaoqiu@xiaobaoqiu:~/cglib_proxy/proxy/javaProxy$ javap -c HelloWithoutInterface\$\$EnhancerByCGLIB\$\$e4e0e0f1.class
...
  final void CGLIB$hello$0();
    Code:
       0: aload_0
       1: invokespecial #36                 // Method proxy/javaProxy/HelloWithoutInterface.hello:()V
       4: return

  public final void hello();
    Code:
       0: aload_0
       1: getfield      #38                 // Field CGLIB$CALLBACK_0:Lnet/sf/cglib/proxy/MethodInterceptor;
       4: dup
       5: ifnonnull     17
       8: pop
       9: aload_0
      10: invokestatic  #42                 // Method CGLIB$BIND_CALLBACKS:(Ljava/lang/Object;)V
      13: aload_0
      14: getfield      #38                 // Field CGLIB$CALLBACK_0:Lnet/sf/cglib/proxy/MethodInterceptor;
      17: dup
      18: ifnull        37
      21: aload_0
      22: getstatic     #44                 // Field CGLIB$hello$0$Method:Ljava/lang/reflect/Method;
      25: getstatic     #46                 // Field CGLIB$emptyArgs:[Ljava/lang/Object;
      28: getstatic     #48                 // Field CGLIB$hello$0$Proxy:Lnet/sf/cglib/proxy/MethodProxy;
      31: invokeinterface #54,  5           // InterfaceMethod net/sf/cglib/proxy/MethodInterceptor.intercept:(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;Lnet/sf/cglib/proxy/MethodProxy;)Ljava/lang/Object;
      36: return
      37: aload_0
      38: invokespecial #36                 // Method proxy/javaProxy/HelloWithoutInterface.hello:()V
      41: return
...

遗留问题: (1).为什么一个类会生成多个代理类,各个代理类都是什么用处;

CGLib代理同样存在限制:

(1).private方法无法代理;
(2).final方法无法代理;

private方法和final方法看代理类的字节码会发现,代理类不会这些重写函数(子类没法重写),因此会自动调用父类的。

参考: cglib源码分析(四):cglib 动态代理原理分析

CGLib: The Missing Manual

#1.4 Java动态代理 VS CGLib动态代理

简单总结对比一下两种动态代理:

代理 没有实现interface的类 protected方法 private方法 final类 final方法 构造函数private的类
Java动态代理 不支持 不支持 不支持 支持 支持 支持
CGLib动态代理 支持 支持 不支持 不支持 不支持 不支持

关于CGLib对protected方法的支持,可以在生成的代理类中看到.

1
2
3
4
CGLib报错信息:
final类: Cannot subclass final class proxy.javaProxy.HelloWithFinal
构造方法私有的类: No visible constructors in class proxy.javaProxy.HelloWithoutConstructor
final方法: 不报错,但没有代理逻辑

在性能方面,通常认为Java动态代理生成代理类比CGLib生成代理类快,但是CGLib的代理类运行期性能会优于Java动态代理的代理类。不过通常性能都不是问题,如果确实很关心性能,建议直接使用ASM。

参考: Why do you think CGLib proxies are faster than JDK Proxies?

Implement Your Own Proxy-Based AOP Framework Blog

BeanDefinitionParserDelegate AnnotationDrivenBeanDefinitionParser

参考: Spring加载资源分析:http://www.blogjava.net/heavensay/archive/2013/10/28/405699.html

事务的坑 http://www.ibm.com/developerworks/library/j-ts1/

代理实现选择器: AdviceMode TransactionManagementConfigurationSelector

声明事务切面实现: TransactionInterceptor

事务实现 Connection关闭自动提交 ConnectionHolder来保持Connection

参考: http://openwares.net/java/spring_mybatis_transaction.html http://my.oschina.net/guanzhenxing/blog/214228 http://www.mybatis.org/spring/zh/transactions.html http://tracylihui.github.io/2015/07/28/spring/Spring%E5%A3%B0%E6%98%8E%E5%BC%8F%E4%BA%8B%E5%8A%A1%E7%AE%A1%E7%90%86/ http://www.cnblogs.com/davenkin/archive/2013/02/16/java-tranaction-1.html http://www.importnew.com/12300.html 详细介绍Spring事务管理: http://developer.51cto.com/art/200906/129854.htm spring事务原理1-事务的抽象: http://sqtds.github.io/2014/06/09/2014/spring-tx1/ Spring官方文档Transaction Management: http://docs.spring.io/autorepo/docs/spring/3.2.x/spring-framework-reference/html/transaction.html Spring官方文档Aspect Oriented Programming with Spring: http://docs.spring.io/spring/docs/3.0.x/reference/aop.html StackOverFlow Spring - @Transactional - What happens in background?: http://stackoverflow.com/questions/1099025/spring-transactional-what-happens-in-background Transaction strategies: Understanding transaction pitfalls: http://www.ibm.com/developerworks/library/j-ts1/ Annotation-based Transactions in Spring: http://springinpractice.com/2008/03/18/annotation-based-transactions-in-spring Design principle behind Transaction framework with Spring 3: http://stackoverflow.com/questions/11789857/design-principle-behind-transaction-framework-with-spring-3 Chapter 6. 使用Spring进行面向切面编程(AOP): http://shouce.jb51.net/spring/aop.html wiki: http://wiki.corp.qunar.com/display/~yushen.ma/Spring+3.x-JDBC+Transaction spring事务: http://wiki.corp.qunar.com/pages/viewpage.action?pageId=52084161 spring 事务: http://wiki.corp.qunar.com/pages/viewpage.action?pageId=93338632 aspectj事务: http://wiki.corp.qunar.com/pages/viewpage.action?pageId=92656954

Demo: 编程事务: http://www.tutorialspoint.com/spring/programmatic_management.htm 声明事务: http://www.tutorialspoint.com/spring/declarative_management.htm

@Transactional注解工作原理:http://blog.csdn.net/dslztx/article/details/46636079 分布式事务系列(1.2)Spring的事务体系: https://yq.aliyun.com/articles/39046 spring transaction源码分析–事务架构:http://www.cnblogs.com/davidwang456/p/4309038.html

http://blog.csdn.net/szwangdf/article/details/41516239

AopProxy DefaultAopProxyFactory