设计模式---代理模式

一、静态代理

首先定义接口 

/**
 * @author Siwang Xu
 * @create 2021/9/30-10:17
 * 定义接口
 */
public interface ITeacherDao {
    void teach();
}

 创建被代理类

/**
 * @author Siwang Xu
 * @create 2021/9/30-10:21
 */
public class TeacherDao implements ITeacherDao{

    @Override
    public void teach() {
        System.out.println("老师在上课");
    }
}

创建代理类

**
 * @author Siwang Xu
 * @create 2021/9/30-10:26
 */
public class TeacherDaoProxy implements ITeacherDao {
      //    目标对象,通过接口来聚合
    private ITeacherDao target;

     //  构造器
    public TeacherDaoProxy(ITeacherDao target){
        this.target=target;
    }

    @Override
    public void teach() {
        System.out.println("开始代理、完成某些操作");
        target.teach();
        System.out.println("提交。。。。。");
    }
}

测试代理

/**
 * @author Siwang Xu
 * @create 2021/9/30-10:46
 */
public class Client {
    public static void main(String[] args) {
        //创建目标对象
        TeacherDao teacherDao=new TeacherDao();
        //创建代理对象
        TeacherDaoProxy teacherDaoProxy=new TeacherDaoProxy(teacherDao);
        //通过代理对象调用被代理对象的方法
        teacherDaoProxy.teach();

    }
}

 1) 优点:在不修改目标对象的功能前提下,能通过代理对象对目标功能扩展.
 2) 缺点:因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类
 3) 一旦接口增加方法,目标对象与代理对象都要维护

二、动态代理

 1.JDK动态代理

定义接口

/**
 * @author Siwang Xu
 * @create 2021/10/6-9:06
 */
public interface ITeacherDao {
    void teach();//授课
    void sayHello(String name);
}

目标对象

/**
 * @author Siwang Xu
 * @create 2021/10/6-9:28
 */
public class TeacherDao implements ITeacherDao {
    @Override
    public void teach() {
        System.out.println("老师授课中...");
    }

    @Override
    public void sayHello(String name) {
        System.out.println("Hello"+name);
    }
}

 代理类

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author Siwang Xu
 * @create 2021/10/6-9:07
 */
public class ProxyFactory {
    //维护目标对象
    private Object target;

    //构造器对 target进行初始化
    public ProxyFactory(Object target){
        this.target=target;
    }

    //给目标对象,生成代理对象

    public Object getProxyInsyance(){
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("JDK代理开始");
                        Object returnVal=method.invoke(target,args);
                        System.out.println("JDK代理提交");
                        return returnVal;
                    }
                });
    }
}

 //1. ClassLoader loader :指定当前目标对象使用的类加载器,获取加载器的方法固定。
 //2. Class<?>[] interfaces:目标对象实现的接口类型,使用泛型方法确认类型。
 //3. InvocationHandlerh:事情处理,执行目标对象的方法时,会触发事情处理器方法,会把当前执行的目标对象方法作为参数传入。

测试代理类

/**
 * @author Siwang Xu
 * @create 2021/10/6-9:31
 */
public class Client {
    public static void main(String[] args) {
        //创建目标对象
        ITeacherDao target=new TeacherDao();
        //给目标对象创建代理对象,可以转成ITeacherDao
        ITeacherDao proxyInstance=(ITeacherDao)new ProxyFactory(target).getProxyInsyance();

        //内存中动态生成代理对象
        System.out.println("proxyInstance="+proxyInstance.getClass());
        
        proxyInstance.sayHello("XSW");
System.out.println("===================");
        proxyInstance.teach();
    }
}

 

 Cglib动态代理

1)静态代理和JDK代理模式都要求目标对象是实现一个接口,但是有时候目标对象只是一个单独的对象,并没有实现任何的接口,这个时候可使用目标对象子类来实现代理这就是Cglib代理
2)Cglib代理也叫作子类代理,它是在内存中构建一个子类对象从而实现对目标对象功能扩展,有些书也将Cglib代理归属到动态代理。
3)Cglib 是一个强大的高性能的代码生成包,它可以在运行期扩展java类与实现java接口.它广泛的被许多AOP的框架使用,例如Spring AOP,实现方法拦截
4)在AOP编程中如何选择代理模式:
        1.目标对象需要实现接口,用JDK代理.
        2.目标对象不需要实现接口,用Cglib代理
5)Cglib包的底层是通过使用字节码处理框架ASM来转换字节码并生成新的类

目标类

/**
 * @author Siwang Xu
 * @create 2021/10/6-11:21
 */
public class TeacherDao {
    public String teach(){
        System.out.println("授课中。");
        return "hello";
    }
}

代理类

(需要导入相关包)

 

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * @author Siwang Xu
 * @create 2021/10/6-10:15
 */
public class ProxyFactory  implements MethodInterceptor{

    private Object target;
    public ProxyFactory(Object target){
        this.target=target;
    }

    //返回一个代理对象,是target对象的代理对象
    public Object getProxyInstance(){
        //1.创建一个工具类
        Enhancer enhancer=new Enhancer();
        //2.设置父类
        enhancer.setSuperclass(target.getClass());
        //3.设置回调函数
        enhancer.setCallback(this);
        //4. 创建子类对象,即代理对象
        return enhancer.create();
    }
    //重写intercept方法,会调用目标对象的方法
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("Cglib代理模式开始");
        Object returnVal=method.invoke(target,objects);
        System.out.println("Cglib开始提交");
        return returnVal;
    }
}

测试代理

/**
 * @author Siwang Xu
 * @create 2021/10/6-11:23
 */
public class Client {
    public static void main(String[] args) {
        //创建目标对象
        TeacherDao teacherDao=new TeacherDao();
        //获取代理对象的方法,将目标对象传递给代理对象
        TeacherDao proxyInstance = (TeacherDao) new ProxyFactory(teacherDao).getProxyInstance();
        //执行代理对象方法,触发intecept方法,从而实现对象的调用
        System.out.println(proxyInstance.teach());

    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值