当前位置: 首页 > 工具软件 > jQuery AOP > 使用案例 >

AOP框架的实现

巴宏恺
2023-12-01

AOP的框架的实现

对于一款MVC框架,AOP当然是不可缺少的,这里我们当然也会借鉴spring AOP框架,实现基于切面注解的AOP框架。接下来我们根据代码逐渐分析,这里我们对所有的类(不管有没有父类)均使用cglib。

首先添加一个Aspect(切面)的注解,其中有一个value,主要是让框架可以区分是基于Controller的切面还是,还是基于Service的切面。

import java.lang.annotation.*;

/**
 * 切面注解
 * 只能作用于类上,运行时
 * Created by lizhaoz on 2015/12/20.
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Aspect {
Class<? extends Annotation> value();
}

接着在实现一个代理接口

/**
 * 代理接口
 * Created by lizhaoz on 2015/12/20.
 */
public interface Proxy {

/**
 * 执行链式代理
 * author:Lizhao
 * Date:15/12/20
 * version:1.0
 *
 * @param proxyChain
 *
 * @return
 *
 * @throws Throwable
 */
Object doProxy(ProxyChain proxyChain) throws Throwable;
}

这里我们会执行一个链式代理,按照链上的先后顺序执行,这里传入的参数就是代理链。
对于ProxyChain的实现如下:

public class ProxyChain {
private final Class<?> targetClass; //目标类
private final Object targetObject;//目标对象
private final Method targetMethod;//目标方法
private final MethodProxy methodProxy;//方法代理
private final Object[] methodParams;//方法参数
private List<Proxy> proxyList=new ArrayList<Proxy>(); //代理列表
private int proxyIndex = 0;//代理索引

public ProxyChain(Class<?> targetClass, Object targetObject, Method targetMethod, MethodProxy methodProxy, Object[] methodParams, List<Proxy> proxyList) {
this.targetClass = targetClass;
this.targetObject = targetObject;
this.targetMethod = targetMethod;
this.methodProxy = methodProxy;
this.methodParams = methodParams;
this.proxyList = proxyList;
}
public Object[] getMethodParams(){
return methodParams;
}
public Class<?> getTargetClass(){
return targetClass;
}
public Method getTargetMethod(){
return targetMethod;
}
public Object doProxyChain() throws Throwable{
Object methodResult;
if(proxyIndex<proxyList.size()){
//代理策略,通过proxyIndex来充当代理对象的计数器,若未达到proxyList的上限
//就执行proxy对象的proxy方法
//最后就执行目标对象的业务逻辑方法
methodResult=proxyList.get(proxyIndex++).doProxy(this);
}else {
//执行业务逻辑方法
methodResult=methodProxy.invokeSuper(targetObject,methodParams);
}
return  methodResult;
}
}

在ProxyChain中有很多成员变量,targetClass-目标类,也就是我们需要代理的类,targetObject–目标对象,targetMethod–目标方法,MethodProxy 方法代理,methodParams方法参数,proxyList–代理列表,proxy–代理索引用来记录当前在哪个代理,其中有一个最重要的方法doProxyChain,这个是用来执行方法的逻辑具体分析可以看代码中的注释有详细的解释。

  到目前为止我们还没有用到CGLib,这个时候我们就要使用CGLib了,添加Maven依赖就不必多说了
,如果我们想生成一个代理类就必须使用代理管理器。

 /**
 * 代理管理器
 * 我们使用CGLIB提供的ENhancer#create方法来创建代理对象,将intercept的参数传入ProxyChain的构造器中即可
 * Created by lizhaoz on 2015/12/20.
 */
    public class ProxyManager {
public static <T> T createProxy(final Class<?> targetClass,final List<Proxy> proxyList){
return (T) Enhancer.create(targetClass, new MethodInterceptor() {
@Override
public Object intercept(Object targetObject, Method  targetmethod,
Object[] methodParams, MethodProxy methodProxy) throws Throwable {
return new ProxyChain(targetClass,targetObject,targetmethod,methodProxy,methodParams,
proxyList).doProxyChain();
}
});
}
}

这里使用的createProxy的两个参数一个是目标类,一个是代理列表,Enhancer.create(Class type, Callback callback)也是CGLIB中的方法用来生成CGLIB代理对象,这里用匿名内部类生成一个方法拦截器,intercept方法这里也是拦截方法,每次调用代理对象都会调用这个方法,这里直接使用ProxyChain.doProxyChain开始执行拦截。
在这里我们需要一个统一的切面模板类如下:

/**
 * 切面代理
 * 提供模板方法,让子类方便实现
 * Created by lizhaoz on 2015/12/20.
 */

public abstract class AspectProxy implements Proxy {
private static final Logger LOGGER= LoggerFactory.getLogger(AspectProxy.class);

@Override
public final Object doProxy(ProxyChain proxyChain) throws Throwable{
Object result=null;
Class<?> cls=proxyChain.getTargetClass();
Method method=proxyChain.getTargetMethod();
Object[] params =proxyChain.getMethodParams();
begin();//begin的模板
try{
//拦截的模板
if(intercept(cls,method,params)){
//前置增强的模板
before(cls,method,params);
result =proxyChain.doProxyChain();
after(cls,method,params,result);
}
else {
result = proxyChain.doProxyChain();
}
}catch (Exception e){
LOGGER.error("proxy failure",e);
error(cls,method,params,e);
throw e;
}
finally {
end();
}
return result;
}

public void end() throws Throwable{
}

public void error(Class<?> cls, Method method, Object[] params, Exception e)throws Throwable {

}

public void after(Class<?> cls, Method method, Object[] params, Object result)throws Throwable {

}

public void before(Class<?> cls, Method method, Object[] params) throws Throwable{

}

public boolean intercept(Class<?> cls, Method method, Object[] params)throws Throwable {
return true;
}

public void begin() throws Throwable{
}
}

其中有许多空方法,这些都是采用了模板模式,子类继承他实现即可。AOP的框架基本实现了,现在如何加入AOP,如何把代理类加入进去,接下来需要一个AOP助手类。

  static {
    try{
        //创建代理类和他所要代理的每个类所有集合的映射
        Map<Class<?>,Set<Class<?>>> proxyMap=createProxyMap();
        //根据上面的映射创建得到每个类有哪些代理的映射。
        Map<Class<?>,List<Proxy>> targetMap=createTargetMap(proxyMap);
        //然后遍历目标类,替换目标类的实例为代理对象
        for(Map.Entry<Class<?>,List<Proxy>> targetEntry:targetMap.entrySet()){
            Class<?> targetClass =targetEntry.getKey();
            List<Proxy> proxyList=targetEntry.getValue();
            Object proxy= ProxyManager.createProxy(targetClass,proxyList);
            //添加目标类和代理实例
            BeanHelper.setBean(targetClass,proxy);
        }
    }catch (Exception e){
        LOGGER.error("aop failure",e);
    }

具体实现github地址:https://github.com/lzggsimida123/iframework

 类似资料: