首页 > 其他 > 详细

浅析JDK 动态代理和CGLIB动态代理

时间:2021-05-16 00:29:39      阅读:20      评论:0      收藏:0      [点我收藏+]

浅析JDK 动态代理和CGLIB动态代理

先说说动态代理有什么作用:

  • 可以横向扩展被代理类的功能
  • 可以绕过方法的权限控制,拿到类中的全部方法

动态代理和静态代理有什么区别:

  • 静态代理需要提前知道被代理的类,而动态代理则没有这个限制
  • 静态代理的实现Demo:
public class Object {
	public void doSomething() {
		// 被代理对象的方法
		System.out.Println("被静态代理的对象");
	}
}

public class StaticProxyObject {
	private Object object;
	public StaticProxyObject(Object object) {
		this.object = object;
	}
	
	public void doSomething() {
		// 代理方法
		System.out.Println("执行被代理方法前执行逻辑");
		object.doSomething();
		System.out.Println("执行后代理方法前执行逻辑");
	}
}

JDK是如何实现动态代理的

  • 基于JDK的动态代理,应用到两个主要的类或接口:InvocationHandler和Proxy,先看一个简单的JDK代理实现的Demo:
public class Deer implements DeerI{
    @Override
    public void saySomething() {
        System.out.println("Deer Class say hello");
    }

    @Override
    public void doSomething() {
        System.out.println("Deer Class is cooking");
    }
}

interface DeerI {
    void saySomething();
    void doSomething();
}


class ProxyInvocationHandler implements InvocationHandler {
    private Object target;
    public ProxyInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("method name is:" + method.getName());
        return method.invoke(target, args);
    }
}

class DeerMain {

    public static void main(String[] args) {
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
        DeerI deer = new Deer();
        Class<?>[] interfaces = deer.getClass().getInterfaces();
        ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler(deer);
        Object object = Proxy.newProxyInstance(deer.getClass().getClassLoader(), deer.getClass().getInterfaces(), proxyInvocationHandler);
        DeerI proxyDeer = (DeerI)Proxy.newProxyInstance(deer.getClass().getClassLoader(), deer.getClass().getInterfaces(), proxyInvocationHandler);
        System.out.println("代理对象是:" + proxyDeer);
        proxyDeer.saySomething();

    }
}

invoke的参数Method表明JDK动态代理是基于反射机制实现的,在invoke方法中通过反射可以调用被代理对象的方法,同时可以在调用之前横向插入逻辑扩展功能。

  • JDK动态代理是基于接口实现的,代理对象继承Proxy并实现这个接口。通过代理对象调用代理方法的时候,
    实际调用的是invocationhandler的invode方法。由于Java类只能单继承,所以JDK动态代理的对象必须要有接口。

JDK动态代理和Cglib动态代理的区别:
JDK是基于代理对象的接口实现的,Cglib是基于继承子类实现的

  • 问:Mybatis也是基于JDK动态代理实现的,为什么Mapper接口没有实现类也可以被代理?

代理没有实现类的接口时,扩展的功能被加到了invoke中,invoke的返回值是invoke的返回值。而代理有接口的实现类时,invoke的返回值是被代理对象方法的返回值。

浅析JDK 动态代理和CGLIB动态代理

原文:https://www.cnblogs.com/deer-hang/p/14772767.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!