设计模式---代理模式

 

  • 介绍

什么是代理模式给某一个对象提供一个代理,并且由代理对象控制对原对象的引用。

代理模式的定义给某一个对象提供一个代理,并由代理对象控制对原对象的引用。

代理模式包含如下角色:

ISubject:抽象主题角色,是一个接口。该接口是对象和它的代理共用的接口。

RealSubject:真实主题角色,是实现抽象主题接口的类。

Proxy:代理角色,内部含有对真实对象RealSubject的引用,从而可以操作真实对象。代理对象提供与真实对象相同的接口,以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。

 

  • 实现

  1. 静态代理

静态代理由我们自己去生成的固定的代码进行编译。需要定义接口或者抽象的父类作为抽象目标类,具体目标类和代理类一起实现相同的接口或者是继承相同的类,然后通过调用相同的方法来调用目标对象的方法。

因为代理对象需要与目标对象实现一样的接口,所以会有很多的代理类,类太多。同时,一旦接口增加方法,目标对象与代理对象都要维护。解决此缺点的方法就是可以使用动态代理方式。

public static <T> void main(String[] args) {

// 静态代理

ProxyInterface proxyBase = new ProxyHandler(new ProxyMain());

proxyBase.request();

  }





public class ProxyHandler implements ProxyInterface {

// 目标对象

private ProxyInterface proxy;



/**

 * 构造方法

 *

 * @param ProxyInterface

 *            目标对象

 */

public ProxyHandler(ProxyInterface proxy) {

this.proxy = proxy;

}



@Override

public void request() {

System.out.println("事物开始");

proxy.request();

System.out.println("事物结束");

}



}

 

  1. 动态代理

public interface ProxyInterface {

void request();

}





public class ProxyMain implements ProxyInterface {



@Override

public void request() {

System.out.println("request");

}



}





public class MyInvocationHandler implements InvocationHandler {

// 目标对象

private Object target;

/**

 * 构造方法

 *

 * @param target

 *            目标对象

 */

public MyInvocationHandler(Object target) {

super();

this.target = target;

}



@Override

public Object invoke(Object proxy, Method method, Object[] args)

throws Throwable {

System.out.println("1111111111111");

Object result = null;

System.out.println("事物开始");

result = method.invoke(target, args);

System.out.println("事物结束");

return result;

}



}



public static <T> void main(String[] args) {



// jdk 动态代理实现

ProxyInterface proxy = (ProxyInterface) java.lang.reflect.Proxy

.newProxyInstance(ProxyMain.class.getClassLoader(),

ProxyMain.class.getInterfaces(),

new MyInvocationHandler(new ProxyMain()));

proxy.request();



}
  1. cglib动态代理

 

jdk动态代理要求被代理的目标对象必须是接口,cglib动态代理,也叫子类代理,它是在内存中创建一个子类对象来实现对目标类功能的扩展。CGLIB代理会让生成的代理类继承被代理类,并在代理类中对代理方法进行强化处理,如前置处理和后置处理。在CGLIB底层,其实是借助了ASM这个强大的java字节码生成框架。

引入cglib依赖

    <!-- https://mvnrepository.com/artifact/cglib/cglib -->

        <dependency>

            <groupId>cglib</groupId>

            <artifactId>cglib</artifactId>

            <version>3.2.4</version>

        </dependency>

被代理类:

/**

 * Hello class

 *

 * @author guanhuifang

 * @date 2018/2/25 上午11:52

 **/public class Hello {

    public void sayHello() {

        System.out.println("Hello World!");

    }

}

实现MethodInterceptor接口生成方法拦截器

/**

 * HelloMethodInterceptor class

 *

 * @author guanhuifang

 * @date 2018/2/25 上午11:55

 **/public class HelloMethodInterceptor implements MethodInterceptor {

    @Override

    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {

        System.out.println("之前"+method.getName());

        methodProxy.invokeSuper(o,objects);

        System.out.println("之后"+method.getName());

        return null;

    }

}

客户端验证:

/**

 * Client class

 *

 * @author guanhuifang

 * @date 2018/2/25 上午11:59

 **/public class Client {

    public static void main(String[] args) {

        Enhancer enhancer = new Enhancer();

        enhancer.setSuperclass(Hello.class); //继承被代理类

        enhancer.setCallback(new HelloMethodInterceptor()); //设置回调

        Hello hello = (Hello) enhancer.create(); //生成代理类对象

        hello.sayHello();

    }

}

运行结果:

之前sayHello

Hello World!

之后sayHello

 

Process finished with exit code 0

在enhance.create()创建完代理类对象之后,在代理类调用方法中会被我们实现的方法拦截器HelloMethodInterceptor拦截。如果被代理类hello被final修饰,则hello类不能被继承,即不能被代理。同样,如果被代理类hello类存在final修饰的方法,那么该方法不能被代理。

 

  • 总结(使用场景)

客户端在使用一个功能时,不希望直接使用其接口,而是希望通过一个代理去完成其功能。类似于现实生活中,人们买、租房时常常会通过中介代理,由中介帮客户相关事项,而且代理常常可以为用户完成一些相关性工作,例如办理手续等。

AOP

日志

权限

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值