【Java】调用代理对象的原始方法

本文介绍了在Java Spring中如何利用AOP生成代理对象,并着重讲解了如何在AOP代理中调用原始方法,而不是代理后的方法。通过创建代理工具类AopUtil,实现了获取并执行原始对象的方法。测试部分展示了如何在代理对象上调用原生方法。

一. 说明

  1. Java Spring中使用AOP可以很方便的生成代理对象,从而添加自定义逻辑。
  2. 本文介绍如何调用代理对象的原始方法,而非代理后的方法

二. 原始类

@Component
public class AopTestClass {

    public void method1() {

        System.out.println("method1 execute");
    }
}

三. 系统启动时生成代理对象

  1. proxyMethod:对指定方法添加前后逻辑,生成代理方法
  2. 代理对象根据原始对象是否有接口,使用JDK或CGLib动态代理
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AopTestClassProxy implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {

        return o;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {

        // 代理具体的bean
        if (beanName.contains("aopTestClass")) {

            // 直接对方法进行代理
            return getProxy(bean, invocation -> this.proxyMethod(bean, invocation));

        }
        return bean;
    }

    private Object proxyMethod(Object bean, MethodInvocation invocation) throws Throwable {

        String methodName = invocation.getMethod().getName();

        // 对指定方法进行代理
        if (methodName.equals("method1")) {

            System.out.println("method1 before");

            Object ret = invocation.proceed();

            System.out.println("method1 after");

            return ret;
        }

        Object ret = invocation.proceed();
        return ret;
    }

    // 使用 ProxyFactory 类生成动态代理方法
    public static Object getProxy(Object obj, MethodInterceptor interceptor) {

        ProxyFactory proxy = new ProxyFactory(obj);
        proxy.setProxyTargetClass(true);
        proxy.addAdvice(interceptor);
        return proxy.getProxy();
    }
}

四. 代理工具类

import lombok.SneakyThrows;
import org.springframework.aop.framework.AdvisedSupport;
import org.springframework.aop.framework.AopProxy;
import org.springframework.aop.support.AopUtils;

import java.lang.reflect.Field;

public class AopUtil {

    /**
     * 获取 目标对象
     */
    @SneakyThrows
    public static Object getTarget(Object proxy) {

        // 不是代理对象
        if (!AopUtils.isAopProxy(proxy)) {
            return proxy;
        }

        // jdk代理
        if (AopUtils.isJdkDynamicProxy(proxy)) {

            return getJdkDynamicProxyTargetObject(proxy);

        } else { // cglib代理

            return getCglibProxyTargetObject(proxy);
        }
    }

    // 获取JDK代理的原始对象
    private static Object getJdkDynamicProxyTargetObject(Object proxy) throws Exception {

        Field h = proxy.getClass().getSuperclass().getDeclaredField("h");
        h.setAccessible(true);
        AopProxy aopProxy = (AopProxy) h.get(proxy);

        Field advised = aopProxy.getClass().getDeclaredField("advised");
        advised.setAccessible(true);

        Object target = ((AdvisedSupport) advised.get(aopProxy)).getTargetSource().getTarget();

        return target;
    }

    // 获取 CGLib代理的原始对象
    private static Object getCglibProxyTargetObject(Object proxy) throws Exception {

        Field h = proxy.getClass().getDeclaredField("CGLIB$CALLBACK_0");
        h.setAccessible(true);
        Object dynamicAdvisedInterceptor = h.get(proxy);

        Field advised = dynamicAdvisedInterceptor.getClass().getDeclaredField("advised");
        advised.setAccessible(true);

        Object target = ((AdvisedSupport) advised.get(dynamicAdvisedInterceptor)).getTargetSource().getTarget();

        return target;
    }

}

五. 测试

@Autowired
private AopTestClass aopTestClass;

@Test
public void aopTest() {

    System.out.println("执行代理方法");
    aopTestClass.method1();

    System.out.println();

    System.out.println("执行原生方法");
    AopTestClass result = (AopTestClass) AopUtil.getTarget(this.aopTestClass);
    result.method1();

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值