AOP中用到的两种代理

一、代理基础

1.1 什么是动态代理

代理: 使用jdk的反射机制,创建对象的能力, 创建的是代理类的对象。 而不用你创建类文件。不用写java文件。

动态:在程序执行时,调用jdk提供的方法才能创建代理类的对象。

jdk动态代理,必须有接口,目标类必须实现接口, 没有接口时,需要使用cglib 动态代理

1.2 动态代理作用

  1. 功能增强: 在你原有的功能上,增加了额外的功能。 新增加的功能,叫做功能增强。
  2. 控制访问: 代理类不让你访问目标,例如商家不让用户访问厂家。

1.3 代理的实现方式

1.3.1 静态代理
  1. 代理类是自己手工实现的,自己创建一个java类,表示代理类。
  2. 同时你所要代理的目标类是确定的。
  • 特点:
    • 实现简单
    • 容易理解
  • 缺点:
    • 当你的项目中,目标类和代理类很多时候,有以下的缺点:
      1)当目标类增加了, 代理类可能也需要成倍的增加。 代理类数量过多。
      2)当你的接口中功能增加了, 或者修改了,会影响众多的实现类,厂家类,代理都需要修改。影响比较多。
1.3.2 动态代理

在静态代理中目标类很多时候,可以使用动态代理,避免静态代理的缺点。
1)代理类数量可以很少,
2)当你修改了接口中的方法时,不会影响代理类。

动态代理: 在程序执行过程中,使用jdk的反射机制,创建代理类对象, 并动态的指定要代理目标类。
换句话说: 动态代理是一种创建java对象的能力,让你不用创建TaoBao类,就能创建代理类对象。

参考:

(48条消息) JDK动态代理(介绍理解,如何实现)_TxCode的博客-CSDN博客_jdk动态代理

JDK动态代理

  1. Interface:对于 JDK 动态代理,目标类需要实现一个 Interface。
  2. InvocationHandler:InvocationHandler 是一个接口,可以通过实现这个接口,定义横切逻辑,再通过反射机制(invoke)调用目标类的代码,在次过程,可能包装逻辑,对目标方法进行前置后置处理。
  3. Proxy:Proxy 利用 InvocationHandler 动态创建一个符合目标类实现的接口的实例,生成目标类的代理对象。

使用动态代理步骤

  1. 创建接口,定义目标类要完成的功能
  2. 创建目标实现类
  3. 创建 InvocationHandler 接口的实现类,在invoke方法中完成代理类的功能
    1. 调用目标方法
    2. 增强功能
  4. 使用Proxy类的静态方法,创建代理对象,并把放回置转为接口类型

自己写的示例

//创建接口Factory,表示一个工厂
public interface Factory {

    /**
     * 厂家进行销售
     * @param name 需要传入的参数
     */
    void sell(String name);

    void refund();
}
//创建目标实现类 
public class FactoryImpl implements Factory {
    @Override
    public void sell(String name) {
        System.out.println("厂家生成货物:  " + name);
    }

    @Override
    public void refund() {
        System.out.println("商家退货");
    }
}

//创建 InvocationHandler 接口的实现类,在invoke方法中完成代理类的功能,相当于商家代理销售和退货
public class MyInvocationHandler implements InvocationHandler {

    private Object target;//传入需要代理的类

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

	//根据方法名处理不同的逻辑
        if(method.getName().equals("sell")){
            System.out.println("------------商家代理销售------------- ");
            //调用被代理类的某个方法
            //传入 代理类 , 对应参数
            method.invoke(target,args);

            System.out.println("--------------商家代理销售完成---------------");
        } else if(method.getName().equals("refund")){
            System.out.println("------------商家代理退货------------- ");
            //调用被代理类的某个方法
            //传入 代理类 , 对应参数
            method.invoke(target,args);
            System.out.println("--------------商家代理退货完成---------------");
        }

        return null;
    }


    /**
     * 提供Proxy静态方法,创建代理对象。
     * @return
     */
    public Object getProxy() {
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
    }
}

//主方法,使用示例
public class App {
    public static void main(String[] args) {
        MyInvocationHandler myInvocationHandler = new MyInvocationHandler(new FactoryImpl());
        Factory proxy = (Factory) myInvocationHandler.getProxy();
        proxy.refund();

    }
}

CGLib动态代理

优点

  • 目标类无需实现某个接口
  • 执行效率较高

缺点

  • Cglib原理是针对目标类生成一个子类,覆盖其中的所有方法,所以目标类和方法不能声明为final类型。

示例

//目标类
public class Dog {
    public void run(String name){
        System.out.println("狗"  + name + "--------run");
    }

    public void eat(){
        System.out.println("狗-------------eat");
    }
}

//自定义拦截器
public class MyInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("对目标类的增强!!!");
        methodProxy.invokeSuper(o,objects);
        return null;
    }
}

//主方法
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        //设置目标类的字节码文件
        enhancer.setSuperclass(Dog.class);
        //设置回调函数
        enhancer.setCallback(new MyInterceptor());

        //这里创建正式代理类
        Dog dog = (Dog) enhancer.create();
        //调用代理类的eat方法
        dog.eat();
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值