【java基础】动态代理

因为学习spring框架时涉及到了AOP 面向切面编程,并且使用到了动态代理的知识,所以来写一篇博客纪录下,动态代理相关知识和aop的一些简单知识
首先我们来看下
AOP(面向切面编程) :通俗的说,就是在不动源码的基础上对代码进行增强!通过增强我们可以干好多事,比如修改编码之类的!
那么不对源码进行修改就进行增强的方式,我想到了 三种方法
1.继承
2.装饰者模式
3.动态代理
我们来看下动态代理
首先动态代理就是在不修改原代码基础上,对代码进行增强
目前我知道的动态代理有两类

  1. 基于接口的动态代理 由jdk 提供
  2. 基于子类的动态代理 由cglib提供(spring框架就使用这种,因为你没办法要求每个类都实现了接口,但是只要类不是被final修饰的,就可以继承!)

我们首先来看下基于接口的动态代理
首先我们需要一个代理类,java规定这个类必须实现 InvocationHandler 接口,然后通过该接口的 Invoke 方法来对代码进行增强

我现在要实现的就是 卖水果的人在处理水果的时候,偷偷吃掉了水果,既然是偷偷的,那我就不能告诉顾客!所以我们来增强下
首先我们需要一个代理类,下面上代码!

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

import interfaces.FruitInterface;

public class MyProxy implements InvocationHandler {

    //这里是你一会要增强的那个方法的类,通过下面的构造函数赋值
    private FruitInterface fruit;

    public MyProxy() {
        super();
    }
    public MyProxy(FruitInterface fruit){
        this.fruit = fruit;
    }
    /**
    *下面这个方法就是用来增强代码的,每个被代理类的方法执行前都会经过下面这个方法
    *@param 第一个参数 是代理对象的引用
    *@param 第二个参数 是当前正在执行的方法
    *@param 第三个参数 是当前执行方法的参数
    **/
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("proxy is starting");
        if("deal".equals(method.getName())){
            System.out.println("处理的时候就偷偷吃掉了!");
        }

        Object invoke = method.invoke(fruit, args);//这里就是用了反射来执行方法
        System.out.println("proxy is ending");
        return invoke;
    }
}

既然代理的类有了,我们需要有被代理类,也就是谁要被增强!因为我们是基于接口的的动态代理,所以先建一个简单的接口

public interface FruitInterface {
    public void deal();
    public void end();
}

然后再实现该接口

import interfaces.FruitInterface;

public class FruitImpl implements FruitInterface {

    @Override
    public void deal() {
        System.out.println("fruit is dealing");
    }

    @Override
    public void end() {
        System.out.println("fruit is end!!");
    }

}

然后我们就可以开始增强了

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

import interfaces.FruitInterface;
import interfaces.impl.FruitImpl;
import proxy.MyProxy;

public class EatFruit {

    public static void main(String[] args) {

        FruitInterface fruit = new FruitImpl();
        //获得代理类的handle
        MyProxy handle = new MyProxy(fruit);
        //调用Proxy的newProxyInstance方法获取一个经过增强的对象
        FruitInterface as = (FruitInterface)Proxy.newProxyInstance(fruit.getClass().getClassLoader(), fruit.getClass().getInterfaces(), handle);
        //然后接下来调用已经增强好的对象的方法,你会发现你已经开始偷吃水果了
        //这个过程我们并没有去修改Fruit类的代码而实现了这一目的
        as.deal();
        as.end();
    }

}

那我们再来看一看 基于子类的动态代理,因为是cglib提供的 ,所以我们需要引入jar包

asm-3.1.wso2v1.jar
cglib-2.2.jar

下载地址

https://download.csdn.net/download/u013781343/10552203

这个动态代理我并没有修改什么代码,只是在原来的EatFruit 类中做了相应的变化,下面上代码,具体说明都在注释里

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

import interfaces.FruitInterface;
import interfaces.impl.FruitImpl;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import proxy.MyProxy;

public class EatFruit {

    public static void main(String[] args) {
        FruitInterface fruit = new FruitImpl();

        //cglib实现动态代理
        /**这里用到了Enhancer类的create方法 
        **第一个参数是被代理类的字节码 第二个参数是如何代理,类似于InvocationHandle接口
        **不过我们这里使用的是MethodInterceptor()这个子接口
        **需要我们使用里面的intercept方法来进行方法增强
        **/
        FruitInterface create = (FruitInterface)Enhancer.create(FruitImpl.class, new MethodInterceptor() {
            //执行被代理对象的任何方法都会执行该方法,用法和刚才的 jdk的动态代理一样
            @Override
            public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {

                System.out.println("cglib动态代理开始!");
                if("deal".equals(method.getName())){
                    System.out.println("我又开始偷吃了!");
                }
                method.invoke(fruit, args);

                return null;
            }
        });

        create.deal();
        create.end();
    }

}

这样最终结果是
这里写图片描述
这就是两种动态代理方式,接下里就可以研究一下 AOP 里面的 切入点,通知等知识点了

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值