基于CGLIB手动实现动态代理例子完整代码

基于CGLIB手动实现动态代理例子完整代码

预定流程

在这里插入图片描述
图4-1所示的约定流程如下。
(1)调用拦截器的before()方法;
(2)调用目标方法;
(3)调用目标方法时如果发生异常,则调用afterThrowing()方法;
(4)调用目标方法时如果未发生异常,则调用afterReturning()方法;
(5)调用after()方法;
(6)如果拦截器的useAround()方法返回true,用拦截器的around()方法取代上面的整个流程。

代码结构

在这里插入图片描述

目标对象接口-HelloService

package com.burns.test.test3;

/**
 * 这个接口很简单,就是定义一个sayHello()方法,其中的参数name是名字,这样就可以对该名字说hello了
 */
public interface HelloService {
    public void sayHello(String name);
}

目标对象接口实现类-HelloServiceImpl

package com.burns.test.test3;

/**
 * 这里的代码也很简单,方法sayHello()先判断name是否为空。
 * 如果为空,则抛出异常,告诉调用者参数为空;
 * 如果不为空,则对该名字说hello。
 * 这样,一个非常简单的服务就写好了
 */
public class HelloServiceImpl implements HelloService {
    @Override
    public void sayHello(String name) {
        if (name == null || "".equals(name.trim())) {
            throw new RuntimeException("parameter is null!!");
        }
        System.out.println("hello " + name);
    }
}

拦截器接口-Interceptor

package com.burns.test.test3;

/**
 * 一个拦截器接口,它十分简单,只包含几个方法
 */
public interface Interceptor {
    // 事前方法
    public void before();

    // 事后方法
    public void after();

    /**
     * 取代原有事件方法
     *
     * @param invocation -- 回调参数,可以通过它的proceed()方法回
     *                   调原有事件
     * @return 原有事件返回对象
     * @throws Throwable
     */
    public Object around(Invocation invocation) throws Throwable;

    // 事后返回方法,事件没有发生异常时运行
    public void afterReturning();

    // 事后异常方法,事件发生异常后运行
    public void afterThrowing();

    // 是否使用around()方法取代整个流程,默认为false
    public default boolean useAround() {
        return false;
    }
}

拦截器接口实现类-MyInterceptor

package com.burns.test.test3;

/**
 * 根据拦截器接口的定义来开发一个自己的拦截器——MyInterceptor
 */
public class MyInterceptor implements Interceptor {
    @Override
    public void before() {
        System.out.println("before ......");
    }

    @Override
    public boolean useAround() {
        return true;
    }

    @Override
    public void after() {
        System.out.println("after ......");
    }

    @Override
    public Object around(Invocation invocation) throws Throwable {
        System.out.println("around before ......");
        Object obj = invocation.proceed();
        System.out.println("around after ......");
        return obj;
    }

    @Override
    public void afterReturning() {
        System.out.println("afterReturning......");
    }

    @Override
    public void afterThrowing() {
        System.out.println("afterThrowing......");
    }
}

回调参数-Invocation

package com.burns.test.test3;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;


public class Invocation {
    private Object[] params; // 参数
    private Method method; // 方法
    private Object target; // 目标对象
    private Interceptor interceptor; // 拦截器

    public Invocation(Object target,
                      Method method, Object[] params, Interceptor interceptor) {
        this.target = target;
        this.method = method;
        this.params = params;
        this.interceptor = interceptor;
    }

    // 反射方法
    public Object proceed() throws InvocationTargetException, IllegalAccessException {
        Object retObj = null; // 返回结果
        boolean exceptionFlag = false; // 异常标志位
// 调用拦截器的before()方法
        this.interceptor.before();
        try {
// 使用反射调用原有方法,并保存返回值
            retObj = method.invoke(target, params);
        } catch (Exception ex) {
// 设置异常标志位
            exceptionFlag = true;
        }
        if (exceptionFlag) { // 发生异常则运行拦截器的afterThrowing()方法
            this.interceptor.afterThrowing();
        } else { // 未发生异常则运行拦截器的afterReturning()方法
            this.interceptor.afterReturning();
        }
// 无论发生异常与否,都会运行的拦截器after()方法
        this.interceptor.after();
        return retObj;
    }
/**** setters and getters ****/
}

代理类-ProxyBean

package com.burns.test.test3;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class ProxyBean implements MethodInterceptor {
    // 拦截器
    private Interceptor interceptor = null;
    // 目标对象
    private Object target = null;

    /**
     * 生成代理对象
     *
     * @param target      目标对象
     * @param interceptor 拦截器
     * @return 代理对象
     */
    public static Object getProxy(Object target, Interceptor interceptor) {
        ProxyBean proxyBean = new ProxyBean();
// 创建增强者
        Enhancer enhancer = new Enhancer();
// 设置代理的类
        enhancer.setSuperclass(target.getClass());
// 设置代理对象可以下挂到哪些接口下
        enhancer.setInterfaces(target.getClass().getInterfaces());
// 保存目标对象
        proxyBean.target = target;
// 保存拦截器
        proxyBean.interceptor = interceptor;
// 设置代理对象为proxyBean,运行时会回调代理对象的intercept() 方法
        enhancer.setCallback(proxyBean); // ①
        // 创建动态代理对象
        Object proxy = enhancer.create();
        return proxy;
    }

    /**
     * 代理对象逻辑
     *
     * @param proxy  代理对象
     * @param method 拦截器的方法
     * @param args   方法参数
     * @param mproxy 方法代理
     * @return 返回目标方法和对象
     */
    @Override
    public Object intercept(Object proxy, Method method, Object[] args
            , MethodProxy mproxy)
            throws Throwable {
// 回调对象
        Invocation invocation =
                new Invocation(this.target, method, args, this.interceptor);
        Object result = null;
        if (this.interceptor.useAround()) { // 是否启用环绕通知
            result = this.interceptor.around(invocation);
        } else {
            result = invocation.proceed();
        }
// 返回结果
        return result;
    }
}

测试类-AopTest

package com.burns.test.test3;

public class AopTest {
    public static void main(String[] args) {
        testProxy();
    }

    public static void testProxy() {
// 目标对象
        HelloService helloService = new HelloServiceImpl();
// 获取代理对象,绑定流程
        HelloService proxy = (HelloService) ProxyBean.getProxy(
                helloService, new MyInterceptor());
// 调用方法,该方法将被织入约定的流程中
        proxy.sayHello("张三");
        System.out.println("###############测试异常###############");
// 调用方法,测试异常情况
        proxy.sayHello(null);
    }
}

输出

around before ......
before ......
hello 张三
afterReturning......
after ......
around after ......
###############测试异常###############
around before ......
before ......
afterThrowing......
after ......
around after ......

最后-完整代码例子参考下载

在这里插入图片描述

https://download.csdn.net/download/zp357252539/90542223

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱的叹息

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值