JDK动态代理与CGLIB的区别

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/tyllb1234/article/details/78596823

JDK动态代理和CGLIB字节码生成的区别?

        JDK动态代理只能对实现了接口的类生成代理,而不能针对类;

         CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,因为是继承,所以该类或方法最好不要声明成final。

(1)    JDK动态代理实例:

package com.designpatten.proxy;

/**
 * Created by lenovo on 2017/11/22.
 * 业务接口,提供对外提供的业务功能
 */
public interface UserService {
    /**
     * 目标方法
     */
    void  add();
}
package com.designpatten.proxy;
/**
 * Created by lenovo on 2017/11/22.
 * 业务接口实现类
 */
public class UserServiceImpl implements  UserService{
    @Override
    public void add() {
        System.out.println("这是业务方法!");
    }
}

package com.designpatten.proxy;

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

/**
 * Created by lenovo on 2017/11/22.
 * 创建自己的InvocationHandler,对业务方法进行增强
 */
public class MyInvocationHandler implements InvocationHandler{

    private Object target;

    public MyInvocationHandler(Object target){
        super();
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("--------before-----------");
        //执行目标对象的方法
        Object result = method.invoke(target,args);
        System.out.println("--------after-----------");
        return result;
    }

    /**
     * 获取目标对象的代理对象
     * @return
     */
    public Object getProxy(){
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),target.getClass().getInterfaces(),this);
    }
}
package com.designpatten.proxy;

/**
 * Created by lenovo on 2017/11/22.
 */
public class TestProxy {
    public static void main(String[] args) {
        //实例化目标
        UserService userService = new UserServiceImpl();
        MyInvocationHandler myInvocationHandler = new MyInvocationHandler(userService);
        //根据目标对象生成代理
        UserService proxy =(UserService) myInvocationHandler.getProxy();
        proxy.add();
    }
}
 
运行结果:

--------before-----------
这是业务方法!
--------after-----------

(2) CGLIB使用实例:

package com.designpatten.proxy;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * Created by lenovo on 2017/11/22.
 */
public class EnhancerDemo {
    public static void main(String[] args) {
        Enhancer enhancer  = new Enhancer();
        enhancer.setSuperclass(EnhancerDemo.class);
        enhancer.setCallback(new MethodInterceptorImpl());
        EnhancerDemo demo = (EnhancerDemo)enhancer.create();
        demo.test();
        System.out.println(demo);
    }
    public void test(){
        System.out.println("This is EnhancerDemo Test!");
    }

    private static class  MethodInterceptorImpl implements  MethodInterceptor{

        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            System.err.println("Before invoke"+method);
            Object result = methodProxy.invokeSuper(o,objects);
            System.err.println("After invoke"+method);
            return  result;
        }
    }
}
运行结果:

Before invokepublic void com.designpatten.proxy.EnhancerDemo.test()
This is EnhancerDemo Test!
After invokepublic void com.designpatten.proxy.EnhancerDemo.test()
Before invokepublic java.lang.String java.lang.Object.toString()
Before invokepublic native int java.lang.Object.hashCode()
After invokepublic native int java.lang.Object.hashCode()
After invokepublic java.lang.String java.lang.Object.toString()
com.designpatten.proxy.EnhancerDemoEnhancerByCGLIBbde44821@6a024a67

可以看到在调用System.out.println(test)时,首先调用了toString()方法,然后又调用了hascode(),最后生成了EnhancerDemoEnhancerByCGLIBbde44821@6a024a67这个实例,这个类就是运行时CGLIB产生的。


展开阅读全文

没有更多推荐了,返回首页