The following is the native writing method of CGLib (implemented using the classes in the net.sf.cglib.proxy.* package)
class Foo { public void fun1(){ System.out.println("fun1"); fun2(); } public void fun2() { System.out.println("fun2"); } } class CGlibProxyEnhancer implements MethodInterceptor{ public Object getProxy(Class clazz) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(clazz); enhancer.setCallback(this); return enhancer.create(); } @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.print("before "); Object result = proxy.invokeSuper(obj,args); return result; } } public class Test { public static void main(String[] args) { CGlibProxyEnhancer pf = new CGlibProxyEnhancer(); Foo foo = (Foo) pf.getProxy(Foo.class); foo.fun1(); } }
The print result is:
before fun1
before fun2
It can be seen that although fun2() is called through foo.fun1(), fun()2 can still be proxied.
But if you use the basic writing method of Spring AOP:
class Foo { public void fun1() { System.out.println("fun1"); fun2(); } public void fun2() { System.out.println("fun2"); } } class Before implements MethodBeforeAdvice { public void before(Method method, Object[] objects, Object o) throws Throwable { System.out.print("before "); } } public class TestCGLib { public static void main(String[] args) { Foo foo = new Foo(); BeforeAdvice advice = new Before(); ProxyFactory pf = new ProxyFactory(); pf.setOptimize(true);//启用Cglib2AopProxy创建代理 pf.setProxyTargetClass(true); pf.setTarget(foo); pf.addAdvice(advice); Foo proxy = (Foo) pf.getProxy(); proxy.fun1(); } }
The output result is:
before fun1
fun2
It can be seen that the fun2 method is not proxied.
Why is there such a difference?
Spring’s aop cannot intercept internal method calls. Spring will report the bean of the real object and the proxyBean after proxy. ProxyBean has been enhanced with aspects:
proxyBean is equivalent to:
before
invoke(bean,method)
after
In this way, fun2 is actually called by the actual bean (invoke uses the actual object to execute the method you want to execute), so there is no before effect.
When you actually use cglib, you use proxy beans throughout the process