aop的加载顺序要在IOC加载的前面,即是要实例完代理类之后才在这个实例上注入属性。
实现一个基于注解的aop:
1、定义一个切面注解 Aspect
/** * 切面注解 */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface Aspect { Class extends Annotation> value(); }
2、定义一个代理接口Proxy,定义一个实现这个接口的抽象类(切面代理 AspectProxy)
/** * 代理接口 */ public interface Proxy { /** * 执行链式代理 * @param proxyChain * @return * @throws Throwable */ Object doProxy(ProxyChain proxyChain) throws Throwable; }
/** * 切面代理 */ 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(); try { if (intercept(cls, method, params)) { boolean flag = before(cls, method, params); if(!flag){ return "..."; } 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 begin() { } public boolean intercept(Class> cls, Method method, Object[] params) throws Throwable { return true; } public boolean before(Class> cls, Method method, Object[] params) throws Throwable { return true; } public boolean after(Class> cls, Method method, Object[] params, Object result) throws Throwable { return true; } public void error(Class> cls, Method method, Object[] params, Throwable e) { } public void end() { } }
3、定义一个代理链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 ListproxyList = new ArrayList ();//代理列表 private int proxyIndex = 0;//代理索引 public ProxyChain(Class> targetClass, Object targetObject, Method targetMethod, MethodProxy methodProxy, Object[] methodParams, List 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()) {//如果链还没调用完 methodResult = proxyList.get(proxyIndex++).doProxy(this);//调用切面代理类,切面代理类会回调 } else {//调用完成,执行目标对象的业务逻辑 methodResult = methodProxy.invokeSuper(targetObject, methodParams); } return methodResult; } }
4、定义一个代理管理器 ProxyManager,该类会在项目启动的时候就被调用,用来实例化目标类
* 代理管理器 * */ public class ProxyManager { @SuppressWarnings("unchecked") public staticT createProxy(final Class> targetClass, final List 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();//生成完整的代理链职责实例 } }); } }
5、AOPHelper,负责项目启动时,获取需要生成代理的类,调用ProxyManager,实例化好这些类后保存实例在beans中,后续访问调用将拥有aop功能。
static { try { Map, Set >> proxyMap = createProxyMap();//获取AspectProxy的子类,如果子类有Aspect注解,获取注解中的值,这个值也是个注解类,根据这个注解类去获取所有含有这个注解类的类(这个是基于注解的aop的关键) Map , List > targetMap = createTargetMap(proxyMap);//根据上一步组装将要被代理的目标类的代理链 for (Map.Entry , List > targetEntry : targetMap.entrySet()) {//变量每个需要被代理的类 Class> targetClass = targetEntry.getKey(); List proxyList = targetEntry.getValue(); System.out.println("targetClass:"+targetClass.getName()); System.out.println("proxyList:"+proxyList.get(0).toString()); Object proxy = ProxyManager.createProxy(targetClass, proxyList);//实例化 BeanHelper.setBean(targetClass, proxy);//将实例化好的代理类保存到Beans中 } } catch (Exception e) { LOGGER.error("aop failure", e); } }
------------------------------------------------------至此,一个简单的aop开发完成-----------------------------------------
调用:
/** * 拦截 Controller 所有方法,这里可以做权限控制,日志记录,性能监控等等 */ @Aspect(Controller.class) public class ControllerAspect extends AspectProxy { private static final Logger LOGGER = LoggerFactory.getLogger(ControllerAspect.class); private long begin; @Override public boolean before(Class> cls, Method method, Object[] params) throws Throwable { LOGGER.debug("---------- begin ControllerAspect ----------"); if(true){ return true; } return false; } @Override public boolean after(Class> cls, Method method, Object[] params, Object result) throws Throwable { LOGGER.debug("----------- end ControllerAspect-----------"); if(true){ return true; } return false; } }