DK的动态代理只能针对接口来实现,由Proxy.newProxyInstance()第二个参数能很清楚地意识到这一点。面向接口编程肯定有它自己的好处,但是如果很小很小的一个项目,我们要对每个业务类创建一个接口,也并不一定是件好事吧。
如果不创建接口,而要实现代理,我们需要用到cglib,它是一个第三方的jar包,需要额外导入。
cglib采用非常底层的字节码技术,可以为代理对象创建一个子类,并且在子类中采用方法拦截的技术,拦截所有父类方法的调用,并且织入横切逻辑。
注意,既然是为父类创建一个子类,那么final修饰的方法是不能继承的,所以final修饰的方法是不会被织入横切逻辑的。
目标类:
Java代码
- package spring3.aop.aop4;
- public class Target {
-
- public void do1() {
- System.out.println("Target.do1()");
- }
-
- public void do2(String str) {
- System.out.println("Target.do2(" + str + ")");
- }
-
- public void exe1() {
- System.out.println("Target.exe1()");
- }
-
- public void exe2(String str) {
- System.out.println("Target.exe2(" + str + ")");
- }
-
- public final void exe3() {
- System.out.println("Target.exe3");
- }
- }
创建代理类 CglibProxy
Java代码
- package spring3.aop.aop4;
- import java.lang.reflect.Method;
- import net.sf.cglib.proxy.Enhancer;
- import net.sf.cglib.proxy.MethodInterceptor;
- import net.sf.cglib.proxy.MethodProxy;
- public class CglibProxy implements MethodInterceptor {
-
- private Enhancer enhancer = new Enhancer();
-
- public Object getProxy(Class<?> cls) {
- // 设定被代理类(目标类)
- enhancer.setSuperclass(cls);
- // 实例化代理类
- enhancer.setCallback(this);
- return enhancer.create();
- }
-
- @Override
- public Object intercept(Object obj, Method method, Object[] args,
- MethodProxy proxy) throws Throwable {
- System.out.println("----START----");
- Object result = proxy.invokeSuper(obj, args);
- System.out.println("----END----");
- return result;
- }
- }
测试类:
Java代码
- package spring3.aop.aop4;
- public class ProxyMain {
-
- public static void main(String[] args) {
-
- CglibProxy proxy = new CglibProxy();
- Target childTarget = (Target) proxy.getProxy(Target.class);
- childTarget.do1();
- childTarget.do2("test");
- childTarget.exe1();
- childTarget.exe2("test");
- childTarget.exe3();
- }
- }
测试结果:
Java代码
- ----START----
- Target.do1()
- ----END----
- ----START----
- Target.do2(test)
- ----END----
- ----START----
- Target.exe1()
- ----END----
- ----START----
- Target.exe2(test)
- ----END----
- Target.exe3
这部分没有什么要讲的,大家知道就可以了。
注意,加载cglib时间比jdk的反射时间要长,如果应用中频繁的动态生成新的代理,不建议使用cglib,这个根据具体需求自己判断。
spring的aop是通过jdk动态代理或者cglib动态代理为目标bean织入横切逻辑的。