代理模式

代理模式

代理模式分为静态代理和动态代理,动态代理又分为jdk动态代理和CGLIB动态代理,动态代理的主要目的就是在不改变原有代码的情况下,对原代码的功能进行增强,其中Spirng的Aop ,rpc框架远程调用以及开发中dao层接口调用方法时。

1.静态代理

实现方式:目标对象和代理对象实现相同接口

缺点:接口改变时,目标对象和代理对象都需要维护

定义一个抽象的对象

package com.sj.staticproxy;

public interface Add {

    void save();
}

目标对象对抽象对象做具体实现

package com.sj.staticproxy;

public class Target implements Add {
    @Override
    public void save() {
        System.out.println("添加数据完成");
    }
}


创建代理对象,也对抽象对象进行具体的实现,同时构造函数有对目标对象的引用

ackage com.sj.staticproxy;

public class Proxy  implements Add{
    private Target target;
    public Proxy(Target target) {
        this.target=target;
    }

    @Override
    public void save() {
        System.out.println("准备添加数据");
        target.save();
        System.out.println("关机下班");
    }
}

编写测试类,进行代码测试

public class Test {

    public static void main(String[] args) {
        Proxy proxy = new Proxy(new Target());
        proxy.save();//准备添加数据,数据添加完成 关机下班
    }
}

2.jdk动态代理

jdk动态代理是基于接口的动态代理,也是java虚拟机默认的代理方式,具体实现是依赖反射机制,需要目标对象实现一个接口

定义一个接口

package com.sj.jdkproxy;

public interface User {

    String sing(String s);
    void dance();
}

定义目标对象实现接口

package com.sj.jdkproxy;

public class Target implements User {
    @Override
    public String sing(String s) {
        System.out.println("我会唱歌");
        return s;
    }

    @Override
    public void dance() {
        System.out.println("我会跳舞");
    }
}

使用Proxy的newProxyInstance方法,创建代理对象

package com.sj.jdkproxy;

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

public class JdkProxy {

    public static void main(String[] args) {

        Target target = new Target();//创建目标对象
        newProxyInstance的三个参数:
            第一个:目标对象的类加载器
            第二个:目标对象的接口数组
            第三个:InvocationHandler接口是proxy代理实例调用处理程序实现的一个接口,每一个proxy		    	代理实例都有一个关联的调用处理程序,在代理实例调用方法时,方法调用被编码分派到调用处理程序			 invoke方法。
		User user = (User)Proxy.newProxyInstance(target.getClass().getClassLoader(), 						target.getClass().getInterfaces(), new InvocationHandler() {
            invoke方法的三个参数:
                第一个:调用这个方法的代理实例
     			第二个:要调用的方法
     			第三个:方法调用时所需要的参数
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws 				Throwable {
                Object obj=null;
               if ("sing".equals(method.getName())){
                    System.out.println("前置");
                    obj = method.invoke(target,args);
                     System.out.println("后置");
                }else {
                    method.invoke(target,args);
                }
                return obj;
            }
        });
        String s = user.sing("中国");
        System.out.println(s);
        user.dance();
      /*输出结果:前置
                我会唱歌
                后置
                中国
                我会跳舞*/

    }
}

3.基于父类的动态代理 CGLib

CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑,JDK动态代理与CGLib动态代理均是实现Spring AOP的基础。

创建一个需要被代理的类,也就是父类,底层会通过字节码技术创建这个类的子类,实现动态代理。

package com.sj.cglibProxy;

public class Target {

    public  void  say(){

        System.out.println("hello");
    }


    public void  listen(){

        System.out.println("listen to me...");
    }
}

使用Enhancer 的create方法创建代理对象

package com.sj.cglibproxy;

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

import java.lang.reflect.Method;

public class CglibProxy {

    public static void main(String[] args) {
        Target target= new Target();//创建目标对象
        Target target1 =(Target)Enhancer.create(target.getClass(), new MethodInterceptor() {
            @Override
            public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                System.out.println("前置");
                method.invoke(target,args);
                System.out.println("后置");
                return null;//用于返回带返回值方法的返回值
            }
        });

            target1.say();
            target1.listen();
        /*输出结果:前置
                   hello
                   后置
                   前置
                   listen to me ,,,
                   后置*/
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值