您的位置 首页 java

搞懂java动态代理

什么是 代理模式

代理模式就是为对象提供一种代理,以控制外部对这个对象的访问。

通俗地讲,代理就是二手房中介:

买房 ↔ 代理(拿提成)↔ 买房

什么是静态代理?

 // 接口
public interface Movie {
    void play();
}

// 实现类
public class RealMovie implements Movie {
    @ Override 
    public void play() {
        System.out.println("您正在观看电影 《肖申克的救赎》");
    }
}

// 代理类
public class Cinema implements Movie {
    RealMovie movie;
    public Cinema(RealMovie movie) {
        super();
        this.movie = movie;
    }

    @Override
    public void play() {
        guanggao();
        movie.play();
        guanggao();
    }

    public void guanggao(){
        System.out.println("瓜子二手车");
    }
}  

Cinema影院是Movie的代理类,在执行放电影核心操作的同时,也实现了自己的需求。

代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强。

代理类和被代理类应共同实现一个接口,或共同继承某个类。

什么是动态代理?

JDK 的java.lang.reflect包下,提供了一个Proxy类和一个Invocation handler 接口,通过他们俩可以实现JDK下的动态代理。

InvocationHandler的核心是invoke()方法,用于在调用真实对象方法时,加入扩展功能,如日志、监控等。

Proxy的核心是newInstance()方法,用于生成代理类。

二者通过Proxy.newInstance()方法关联,invocationHandler会作为参数传入Proxy,Proxy在编译时自动生成代理类。

demo:

 // 接口
public interface Subject {
    public String SayHello(String name);
    public String SayGoodBye();
}

// 需要代理的类RealSubject
public class RealSubject implements Subject {
    public String SayHello(String name) {
        return "hello " + name;
    }

    public String SayGoodBye() {
        return " good bye ";
    }
}

// 创建调用处理器
public class InvocationHandlerImpl implements InvocationHandler {
    // 需要代理的对象
    private Object subject;
  
    // 构造函数
    public InvocationHandlerImpl(Object subject) {
        this.subject = subject;
    }

    // invoke()方法负责处理动态代理类上的所有方法调用
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 在调用真实对象方法前添加一些扩展功能
        System.out.println("在调用之前,我要干点啥呢?");
        //当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
        Object returnValue = method.invoke(subject, args);
        // 在调用真实对象方法后添加一些扩展功能
        System.out.println("在调用之后,我要干点啥呢?");
        return returnValue;
    }
}

// 实现动态代理
public class DynamicProxyDemonstration {
    public static void main(String[] args) {
        // 需要被代理的对象
        Subject realSubject = new RealSubject();
        // 代理对象
        Subject subject = (Subject) Proxy.newProxyInstance(
            realSubject.getClass().getClassLoader(),
            realSubject.getClass().getInterfaces(),
            new InvocationHandlerImpl(realSubject));
        // 通过代理对象调用真实对象的方法
        String hello = subject.SayHello("jiankunking");
    }
}  

为什么需要动态代理?

如果我们想扩展类的功能,且不能修改类,那么静态代理可以实现。

如果我们要对很多的类扩展功能,如加日志、监控等,静态代理就需要一一创建代理类,而动态代理只需要定义好InvocationHandler的实现类逻辑即可。

动态代理和反射的关系?

1、动态代理核心类:InvocationHandler、Method、Proxy,都在java.lang.reflect反射包内。

2、通过InvocationHandler的invoke()方法调用真实对象的方法时,需要传入Method对象,这里使用的就是 反射机制

3、Proxy.newProxyInstance()传入ClassLoader对象来动态创建代理类,使用的是反射机制。

cglib和jdk动态代理区别?

JDK动态代理是通过反射类Proxy、InvocationHandler 回调 接口实现的,所以只能对该类所实现接口中定义的方法进行代理,有一定的局限性。

cglib 动态代理,不受代理类必须实现接口的限制,原理是动态生成被代理类的子类。

文章来源:智云一二三科技

文章标题:搞懂java动态代理

文章地址:https://www.zhihuclub.com/191392.shtml

关于作者: 智云科技

热门文章

网站地图