自行一个简单类似Spring AOP(Jdk方式)的框架
Posted javartisan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自行一个简单类似Spring AOP(Jdk方式)的框架相关的知识,希望对你有一定的参考价值。
Spring AOP有两种实现方式,一种是基于JDK的,另一种是基于Cglib的,本文模拟Spring的Jdk实现方式自行实现一个简单的小框架,目的是熟悉思想。
基于JDK的动态代理,最终的一个类是InvocationHandler,InvocationHandler可以理解为一个方法调用器,在对方法进行增强时候,代理类会拦截到目标对象上的方法,然后将拦截的方法传递给InvocationHandler的invoke方法,在invoke中触发方法调用,此时就可以对方法调用前后进行逻辑增强。因此需要我们实现一个方法调用器,代码如下:
import org.springframework.util.StringUtils;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* 方法调用器
* @param <T>
*/
public class ProxyInvocationHandler<T> implements InvocationHandler
private T target;
public ProxyInvocationHandler(T target)
this.target = target;
private Advice[] advices;
private String beforeMethodName = "before";
private String afterMethodName = "after";
private Method beforeMethod;
public Advice[] getAdvices()
return advices;
public void setAdvices(Advice[] advices)
this.advices = advices;
private Method afterMethod;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
AdviceParam adviceParam = new AdviceParam();
adviceParam.setTarget(target);
adviceParam.setParams(args);
adviceParam.setMethod(method);
//调用前增强
for (int i = 0; i < advices.length; i++)
Advice advice = advices[i];
if (!StringUtils.isEmpty(beforeMethodName))
beforeMethod = getMethod(advice, beforeMethodName);
beforeMethod.invoke(advice, adviceParam);
// 拦截方法调用
Object result = method.invoke(target, args);
adviceParam.setResult(result);
// 调用之后增强
for (int i = advices.length - 1; i >= 0; i--)
Advice advice = advices[i];
if (!StringUtils.isEmpty(afterMethodName))
afterMethod = getMethod(advice, afterMethodName);
afterMethod.invoke(advice, adviceParam);
return adviceParam.getResult();
/**
* 可以考虑添加cache提高性能
*
* @param name
* @return
*/
public Method getMethod(Advice advice, String name)
if (!StringUtils.isEmpty(name))
Method[] methods = advice.getClass().getDeclaredMethods();
for (Method method : methods)
if (method.getName().equalsIgnoreCase(name))
method.setAccessible(true);
return method;
return null;
方法调用器便编写好了;Spring中对于增强的逻辑进行了一些封装抽象,我们这里面也模拟进行了一些简单的封装抽象。封装的对象有Advice,Advice就是增强逻辑的实现,Advice中有两个方法,分别是前置增强,后置增强(更多增强类似);当拦截的方法传递invoke方法时候便会对前置后置增强逻辑进行调用,以达到增强的目的。
接下来一步便是生成代理类,Spring中使用工厂的方式进行生成代理类,本示例模拟Spring的设计进行简单实现一个代理类生成工厂,先给出类的继承结构:
其中AopConfig是用于存储Aop的配置信息,ProxyFactory是一个抽象工厂,后序可以分为JDK与Cglib两种实现,本文给出JDK实现:
import java.lang.reflect.Proxy;
public class JdkProxyFactory<T> extends ProxyFactory<T>
@Override
public T getProxy()
ProxyInvocationHandler handler = new ProxyInvocationHandler(this.getTarget());
handler.setAdvices(this.getAdvices());
return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), this.getClazz(), handler);
到此也就实现了一个简单的Aop框架,接下来就可以测试,增强代码:
import com.javartisan.service.jdk.proxy.Advice;
import com.javartisan.service.jdk.proxy.AdviceParam;
public class LogAdvice implements Advice
@Override
public Object before(AdviceParam args)
System.out.println("before = " + args);
return null;
@Override
public Object after(AdviceParam args)
System.out.println("after = " + args);
return null;
测试代码:
import com.javartisan.service.UserService;
import com.javartisan.service.UserServiceImpl;
import com.javartisan.service.jdk.proxy.JdkProxyFactory;
import com.javartisan.service.jdk.proxy.ProxyFactory;
import java.util.Arrays;
public class JdkProxy
public static void main(String[] args)
UserService userService = new UserServiceImpl();
ProxyFactory<UserService> proxyFactory = new JdkProxyFactory<>();
proxyFactory.setTarget(userService);
proxyFactory.setClazz(new Class[]UserService.class);
proxyFactory.setAdvices(Arrays.asList(new LogAdvice(), new LogAdvice()));
UserService proxy = proxyFactory.getProxy();
System.out.println(proxy.login("daxin"));
// proxy是代理类
System.out.println(proxy.getClass());
输出:
before = AdviceParamtarget=com.javartisan.service.UserServiceImpl@2ff4acd0, params=[daxin], method=public abstract boolean com.javartisan.service.UserService.login(java.lang.String), result=null
before = AdviceParamtarget=com.javartisan.service.UserServiceImpl@2ff4acd0, params=[daxin], method=public abstract boolean com.javartisan.service.UserService.login(java.lang.String), result=null
login false defalut
after = AdviceParamtarget=com.javartisan.service.UserServiceImpl@2ff4acd0, params=[daxin], method=public abstract boolean com.javartisan.service.UserService.login(java.lang.String), result=false
after = AdviceParamtarget=com.javartisan.service.UserServiceImpl@2ff4acd0, params=[daxin], method=public abstract boolean com.javartisan.service.UserService.login(java.lang.String), result=false
false
class com.sun.proxy.$Proxy0
Github仓库位置:https://github.com/javartisan/javartisan-cglib ,欢迎点星。
以上是关于自行一个简单类似Spring AOP(Jdk方式)的框架的主要内容,如果未能解决你的问题,请参考以下文章