基于JDK动态代理/Cglib代理,结合MethodInterceptor实现代理对象的切面功能

我们都知道,java中的代理分为JDK动态代理和Cglib代理,JDK动态代理是基于反射创建代理对象的,而Cglib是通过字节码技术实现的代理对象创建,使用代理对象的强大作用我们都很清楚,其中spring 中 aop 的核心思想就是基于代理对象的创建,并在切点处织如切面,从而实现aop,今天我们就来实现一下基于JDK动态代理和Cglib代理实现切面功能。

1.AopProxy(interface),定义获取代理对象的方法,具体交由子类实现。

public interface AopProxy {
    /**
     * 获取代理对象
     * @return
     */
    Object getInstance();
}
  1. 具体实现

Jdk动态代理

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

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

/**
 * JDK 动态代理
 */
public class JdkDynamicProxy implements AopProxy{

    private AspectSupport aspectSupport;

    public JdkDynamicProxy(AspectSupport aspectSupport) {
        this.aspectSupport = aspectSupport;
    }

    @Override
    public Object getInstance() {
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                aspectSupport.getTargetSource().targetInterfaces(),new Handler());
    }

    private class Handler implements InvocationHandler{

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            MethodMatcher methodMatcher = aspectSupport.getMethodMatcher();
            if (methodMatcher.matches(method)){
                MethodInterceptor methodInterceptor = aspectSupport.getMethodInterceptor();
                return methodInterceptor.invoke(new ReflectInvocation(args,method,aspectSupport.getTargetSource().getTarget()));
            }
            return method.invoke(aspectSupport.getTargetSource(),args);
        }
    }

    private class ReflectInvocation implements MethodInvocation {
        private Object[] args;
        private Method method;
        private Object target;

        public ReflectInvocation(Object[] args, Method method, Object target) {
            this.args = args;
            this.method = method;
            this.target = target;
        }

        @Override
        public Object[] getArguments() {
            return args;
        }

        @Override
        public Object proceed() throws Throwable {
            return method.invoke(target,args);
        }

        @Override
        public Object getThis() {
            return target;
        }

        @Override
        public AccessibleObject getStaticPart() {
            return method;
        }

        @Override
        public Method getMethod() {
            return method;
        }
    }
}

Cglib代理

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import org.aopalliance.intercept.MethodInvocation;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Method;

/**
 * Cglib 代理
 */
public class CglibProxy implements AopProxy{
    private AspectSupport aspectSupport;

    public CglibProxy(AspectSupport aspectSupport) {
        this.aspectSupport = aspectSupport;
    }

    @Override
    public Object getInstance() {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(aspectSupport.getTargetSource().targetClass());
        enhancer.setInterfaces(aspectSupport.getTargetSource().targetInterfaces());
        enhancer.setCallback(new CglibMethodInterceptor(aspectSupport));
        return enhancer.create();
    }

    // 这个类类似于 InvocationHandler
    private class CglibMethodInterceptor implements MethodInterceptor{
        private AspectSupport aspectSupport;

        public CglibMethodInterceptor(AspectSupport aspectSupport) {
            this.aspectSupport = aspectSupport;
        }

        @Override
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            MethodMatcher methodMatcher = aspectSupport.getMethodMatcher();
            if (methodMatcher != null && methodMatcher.matches(method)){
                return aspectSupport.getMethodInterceptor().invoke(new CglibMethodInvocation(args,method,aspectSupport.getTargetSource().getTarget()));
            }
            return method.invoke(aspectSupport.getTargetSource().getTarget(),args);
        }
    }


    private class CglibMethodInvocation implements MethodInvocation{
        private Object[] args;
        private Method method;
        private Object target;

        public CglibMethodInvocation(Object[] args, Method method, Object target) {
            this.args = args;
            this.method = method;
            this.target = target;
        }

        @Override
        public Object[] getArguments() {
            return args;
        }

        @Override
        public Object proceed() throws Throwable {
            return method.invoke(target,args);
        }

        @Override
        public Object getThis() {
            return target;
        }

        @Override
        public AccessibleObject getStaticPart() {
            return method;
        }

        @Override
        public Method getMethod() {
            return method;
        }
    }
}
  1. 切点接口(Pointcut)
/**
 * 切点
 */
public interface Pointcut {

    /**
     * 类匹配
     * @return
     */
    ClassFilter getClassFilter();

    /**
     * 方法匹配
     * @return
     */
    MethodMatcher getMethodMatcher();
  1. 类匹配接口

/**
 *
 * 通过配置的切点表达式进行类匹配
 */
public interface ClassFilter {
    /**
     * 是否匹配
     * @param clazz
     * @return
     */
    boolean matches(Class<?> clazz);
}

5.方法匹配接口

import java.lang.reflect.Method;

/**
 *
 * 通过配置的切点表达式进行方法匹配
 */
public interface MethodMatcher {
    /**
     * 是否匹配
     * @param method
     * @return
     */
    boolean matches(Method method);
}
  1. 切点,类匹配,方法匹配实现类
    注意: 切点表达式采用 aspectj 中的PointcutExpression实现
    通过PointcutParser(切点解析器)生成一个PointcutExpression 对象,通过这个对象实现方法和类的匹配功能。
import org.aspectj.weaver.tools.PointcutExpression;
import org.aspectj.weaver.tools.PointcutParser;
import org.aspectj.weaver.tools.PointcutPrimitive;

import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;

/**
 * 切点表达式具体实现
 * 这个类主要是通过配置的切点表达式实现类和方法的匹配功能
 */
public class AspectJExpressionPointcut implements Pointcut,ClassFilter,MethodMatcher{
    private static final Set<PointcutPrimitive> PRIMITIVES = new HashSet<>();
    static {
        PRIMITIVES.add(PointcutPrimitive.EXECUTION);
    }
    private final PointcutExpression pointcutExpression;
    public AspectJExpressionPointcut(String execution){
        PointcutParser parser = PointcutParser
                .getPointcutParserSupportingSpecifiedPrimitivesAndUsingContextClassloaderForResolution(PRIMITIVES);
        pointcutExpression = parser.parsePointcutExpression(execution);
    }

    @Override
    public boolean matches(Class<?> clazz) {
        return pointcutExpression.couldMatchJoinPointsInType(clazz);
    }

    @Override
    public boolean matches(Method method) {
        return pointcutExpression.matchesMethodExecution(method).alwaysMatches();
    }

    @Override
    public ClassFilter getClassFilter() {
        return this;
    }

    @Override
    public MethodMatcher getMethodMatcher() {
        return this;
    }
}

7.TargetSource(封装被代理对象)

/**
 * 封装被代理对象,
 * JDK 动态代理通过生成接口的实现类创建代理对象
 * Cglib通过生成类的子类实现代理对象的创建
 */
public class TargetSource {
    private Object target;

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

    public Object getTarget(){
        return target;
    }

    public Class<?> targetClass(){
        return target.getClass();
    }

    public Class<?>[] targetInterfaces(){
        return target.getClass().getInterfaces();
    }
}

8.AspectSupport(切面支持类)

import org.aopalliance.intercept.MethodInterceptor;

/**
 * 切面支持
 * 封装 被代理对象
 * MethodInterceptor(方法拦截器,在方法拦截器中实现具体的代理逻辑)
 * MethodMatcher(方法匹配器)
 */
public class AspectSupport {
    private TargetSource targetSource;

    private MethodInterceptor methodInterceptor;

    private MethodMatcher methodMatcher;

    public AspectSupport(TargetSource targetSource, MethodInterceptor methodInterceptor, MethodMatcher methodMatcher) {
        this.targetSource = targetSource;
        this.methodInterceptor = methodInterceptor;
        this.methodMatcher = methodMatcher;
    }

    public TargetSource getTargetSource() {
        return targetSource;
    }

    public MethodInterceptor getMethodInterceptor() {
        return methodInterceptor;
    }

    public MethodMatcher getMethodMatcher() {
        return methodMatcher;
    }
}

9.测试类
UserService
UserServiceInterceptor
UserServiceImpl
Main

public interface UserService {
    String sayHello(String name);
}

public class UserServiceImpl implements UserService{
    @Override
    public String sayHello(String name) {
        System.out.println("hello -->" + name);
        return "hello -->" + name;
    }
}
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

/**
	这里在切点处实现了具体的切面逻辑
*/
public class UserServiceInterceptor implements MethodInterceptor {

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        long start = System.currentTimeMillis();
        try {
            return invocation.proceed();
        }finally {
            long timeTakeUp = System.currentTimeMillis() - start;
            System.out.println("方法执行耗时-->" + timeTakeUp);
        }

    }
}
import aop.test.UserService;
import aop.test.UserServiceImpl;
import aop.test.UserServiceInterceptor;

public class Main {
    public static void main(String[] args) {
        UserService userService = new UserServiceImpl();
        String execution = "execution(* aop.test.UserService.*(..))";
        AspectSupport aspectSupport = new AspectSupport(
                new TargetSource(userService),
                new UserServiceInterceptor(),
                new AspectJExpressionPointcut(execution)
        );
        //UserService instance = (UserService)new CglibProxy(aspectSupport).getInstance();
        UserService instance = (UserService)new JdkDynamicProxy(aspectSupport).getInstance();

        String result = instance.sayHello("夏天");
        System.out.println("result -- >" + result);
    }
}

在这里插入图片描述
从上面的结果可以看到,直接生成(new UserServuiceImpl)的UserService对象被代理对象代理了,并且在具体的切点处加入了切面逻辑。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值