Java静态代理和动态代理

静态代理:

被代理接口:

public interface Movie {

    void play();

}

真正的被代理类:

public class CaptainAmericaMovie implements Movie {
    @Override
    public void play() {
        System.out.println("普通影厅正在播放的电影是《美国队长》");
    }
}

通过静态代理实现的代理类:

public class MovieStaticProxy implements Movie {

    Movie movie;

    public MovieStaticProxy(Movie movie) {
        this.movie = movie;
    }

    @Override
    public void play() {
        playStart();
        movie.play();//原方法
        playEnd();
    }

    //增强方法
    public void playStart() {
        System.out.println("电影开始前正在播放广告");
    }

    public void playEnd() {
        System.out.println("电影结束了,接续播放广告");
    }
}

用户调用:

    public static void main(String[] args) {
        Movie captainAmericaMovie = new CaptainAmericaMovie();
        Movie movieStaticProxy = new MovieStaticProxy(captainAmericaMovie);
        movieStaticProxy.play();
    }

静态代理缺点:

  • 代理对象需要与目标对象实现一样的接口,所以会有很多代理类,类太多.同时,一旦接口增加方法,目标对象与代理对象都要维护。
jdk动态代理:

动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java 反射机制可以生成任意类型的动态代理类。

代理接口:

public interface VIPMovie {

    void vipPlay();

}

代理类:

public class IronManVIPMovie implements VIPMovie {
    @Override
    public void vipPlay() {
        System.out.println("VI影厅正在播放的电影是《钢铁侠》");
    }
}

通过jdk动态代理生成的类:

public class MyInvocationHandler implements InvocationHandler {

    private Object object;

    public MyInvocationHandler(Object object) {
        this.object = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        playStart();
        //1.类实例
        //2.函数中的参数
        Object invoke = method.invoke(object, args);
        playEnd();
        return invoke;
    }

    public void playStart() {
        System.out.println("电影开始前正在播放广告");
    }

    public void playEnd() {
        System.out.println("电影结束了,接续播放广告");
    }
}

调用:


    public static void main(String[] args) {
    	// VIP 影厅《钢铁侠》
        IronManVIPMovie ironManVIPMovie = new IronManVIPMovie();
        InvocationHandler invocationHandler = new MyInvocationHandler(ironManVIPMovie);
        // 1.被代理类加载器,表示由哪个类来生成代理对象
        // 2.一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口
        // 3.一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上
        VIPMovie dynamicProxy = (VIPMovie) Proxy.newProxyInstance(IronManVIPMovie.class.getClassLoader(),IronManVIPMovie.class.getInterfaces(), invocationHandler);
        dynamicProxy.vipPlay();


        // 把上面的静态代理也实现一遍:普通影厅《美国队长》
        CaptainAmericaMovie captainAmericaMovie = new CaptainAmericaMovie();
        InvocationHandler invocationHandler1 = new MyInvocationHandler(captainAmericaMovie);
        Movie dynamicProxy1 = (Movie) Proxy.newProxyInstance(CaptainAmericaMovie.class.getClassLoader(),CaptainAmericaMovie.class.getInterfaces(), invocationHandler1);
        dynamicProxy1.play();
    }
CGLIB动态代理:

被代理类:

public class HelloConcrete {
    public String sayHello(String str) {
        return "HelloConcrete: " + str;
    }
}

实现类:

/**
 * 首先实现一个MethodInterceptor,方法调用会被转发到该类的intercept()方法。
 */
public class MyMethodInterceptor implements MethodInterceptor {

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("------" + Arrays.toString(args));
        return methodProxy.invokeSuper(obj, args);
    }

    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        //在需要使用HelloConcrete的时候,通过CGLIB动态代理获取代理对象。
        enhancer.setSuperclass(HelloConcrete.class);
        enhancer.setCallback(new MyMethodInterceptor());
        HelloConcrete hello = (HelloConcrete) enhancer.create();
        System.out.println(hello.sayHello("I love you!"));
    }
}

代理优点:

  • 代理模式在客户端与目标对象之间起到一个中介作用和保护目标对象的作用
  • 代理对象可以扩展目标对象的功能
  • 代理模式能将客户端与目标对象分离,在一定程度上降低了系统的耦合度。

参考:
https://www.cnblogs.com/carpenterlee/p/8241042.html

你可能感兴趣的:(设计模式)