Java两种动态代理

一. jdk动态代理

1. jdk动态代理实现原理

jdk动态代理是jdk原生就支持的一种代理方式,它的实现原理,就是通过让目标类和代理类实现同一接口,代理类持有目标类对象,来达到方法拦截的作用,这样通过接口的方式有两个弊端,一个是必须保证target类有接口,第二个是如果想要对target类的方法进行代理拦截,那么就要保证这些方法都要在接口中声明,实现上略微有点限制。
jdk动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用业务方法前调用InvocationHandler处理。 代 理 类 必 须 实 现 I n v o c a t i o n H a n d l e r 接 口 , 并 且 , J D K 动 态 代 理 只 能 代 理 实 现 了 接 口 的 类 , 没 有 实 现 接 口 的 类 是 不 能 实 现 J D K 动 态 代 理 。 \color{red}{代理类必须实现InvocationHandler接口,并且,JDK动态代理只能代理实现了接口的类,没有实现接口的类是不能实现JDK动态代理。} InvocationHandlerJDKJDK 结合下面案例代码来看就比较清晰了。

2.案例

接口:

public interface Dongwu {
    void pao();
    void zou();
}

Java两种动态代理_第1张图片
接口实现类 :

public class Dog implements Dongwu{
    @Override
    public void pao() {
        System.out.println("pao====");
    }

    @Override
    public void zou() {
        System.out.println("zou====");

    }
}

代理增强类:

public class ProxyHandler implements InvocationHandler {
    private Object object;
    
    public ProxyHandler(Object object){
        this.object = object;
    }
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Exception
    {
        before();
        Object invoke = method.invoke(object, args);
        after();
        return invoke;
    }
    // 生成代理类
    public Object CreatProxyedObj()
    {
        return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), new ProxyHandler(object));
    }
    public void after(){
        System.out.println("之后处理。。。。。。。。");
    }
    public void before(){
        System.out.println("之前处理。。。。。。。。");
    }
}

Java两种动态代理_第2张图片
测试类:

public class Test {
    public static void main(String[] args) {
        Dongwu dog = new Dog();
        Dongwu o = (Dongwu)new ProxyHandler(dog).CreatProxyedObj();// 强制转换类型必须是接口
        o.pao();
    }
}

Java两种动态代理_第3张图片
打印结果:
Java两种动态代理_第4张图片
步骤总结:

1、编写需要被代理的类和接口(我这里就是OrderServiceImpl、OrderService);

2、编写代理类(例如我这里的DynamicLogProxy),需要实现InvocationHandler接口,重写invoke方法;

3、使用Proxy.newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h)动态创建代理类对象,通过代理类对象调用业务方法。

二.cglib动态代理:

1. cglib实现原理

基于操作字节码,通过加载代理对象的类字节码,为代理对象创建一个子类,并在子类中拦截父类方法并织入方法增强逻辑。底层是依靠ASM(开源的java字节码编辑类库)操作字节码实现的。

2. 案例

在上面几个类的基础上新加了一个没有实现接口的类
新加类:

public class Person {
    public void eat(){
        System.out.println("吃饭");
    }
    public void pao(){
        System.out.println("pao");
    }
}

Java两种动态代理_第5张图片

cjlib代理类:

public class ProxyHandler implements MethodInterceptor {
    private Object object;
    public void before(){
        System.out.println("之前处理。。。。。。。。");
    }
    public void after(){
        System.out.println("之后处理。。。。。。。。");
    }
    public ProxyHandler(Object object){
        this.object = object;

    }
    public Object CreatProxyedObj() {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(this.object.getClass());
        // 设置回调方法
        enhancer.setCallback(this);
        // 返回代理对象
        return enhancer.create();
    }
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        before();
        Object result = methodProxy.invokeSuper(o, objects);
        after();
        return result;
    }
}

Java两种动态代理_第6张图片

3. 测试

public class Test {
    public static void main(String[] args) {
        Person per = new Person();
        Person o= (Person)new ProxyHandler(per).CreatProxyedObj();
        o.pao();
    }
}

Java两种动态代理_第7张图片

打印结果:
Java两种动态代理_第8张图片

三.两种动态代理总结:

1.使用JDK动态代理,目标类必须实现的某个接口,如果 某 个 类 没 有 实 现 接 口 \color{red}{某个类没有实现接口} 则不能生成代理对象。
2.CGLIB通过继承的方式进行代理、无论目标对象没有没实现接口都可以代理,但是 无 法 处 理 f i n a l \color{red}{无法处理final} final的情况(final修饰的方法不能被覆写)
3.性能方面:JDK > CGLIB

你可能感兴趣的:(java,jdk,proxy)