栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

面试官:你实现过 AOP 吗?AOP的简单实现,现在奉上

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

面试官:你实现过 AOP 吗?AOP的简单实现,现在奉上

手写 AOP 1.0实现
  1. 基于 CGLib实现动态代理

    JDK 动态代理需要被代理的类必须继承某一个接口

    基于ASM的CGLib,可以为被代理的类动态生成子类,以解决 JDK动态代理对接口的束缚

  2. 实现 @Aspect、@Order 注解

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Aspect {
        // 表示当前被 Aspect 标记的横切逻辑,会织入到被属性逻辑标记的那些类中
        Class value();
    }
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Order {
        // 规定value越小优先级越高
        int value();
    }
    
  3. 实现 DefaultAspect 所有切面必须继承 DefaultAspect

    public abstract class DefaultAspect {
        
        public void before(Class targetClass, Method method,Object[] args) throws Throwable{
    
        }
    
        
        public Object afterReturning(Class targetClass, Method method,Object[] args,Object returnValue)throws Throwable{
            return returnValue;
        }
    
        
        public void afterThrowing(Class targetClass, Method method,Object[] args,Throwable e) throws Throwable{
    
        }
    }
    
    
  4. Aspect的排序以及Advice的定序执行

    public class AspectInfo {
        private int orderIndex;
        private DefaultAspect aspectObject;
    }
    

    将 @Order 的值与 Aspect 的实现放入 List中,并将其按照 @Order 的值进行排序,以实现 Advice 的定序执行

  5. 横切逻辑的织入

    通过 CGLib 实现横切逻辑的织入

        @Override
        public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
            Object returnValue = null;
            // 1. 按照order的顺序升序执行完所有Aspect的before方法
            invokeBeforeAdvices(method, args);
            try {
                // 2. 执行被代理类的方法
                returnValue = methodProxy.invokeSuper(proxy, args);
                // 3. 如果被代理方法正常返回,则按照order的顺序降序执行完所有的 Aspect 的afterReturning方法
                returnValue = invokeAfterReturningAdvices(method, args, returnValue);
            } catch (Exception e) {
                // 4. 如果被代理方法抛出异常,则按照order的顺序降序执行完所有 Aspect 的afterThrowing方法
                invokeAfterThrowingAdives(method, args, e);
            }
            return returnValue;
        }
    
1.0的短板

Pointcut 粒度只能支持到注解级别,即只能筛选出被诸如 @Controller @Service 等注解标记的类的集合进行横切逻辑的织入

2.0 引入 AspectJ 的表达式解析功能
   
   private PointcutExpression pointcutExpression;

   public PointcutLocator(String expression) {
       this.pointcutExpression = pointcutParser.parsePointcutExpression(expression);
   }

   
   public boolean roughMatches(Class targetClass) {
       // 只能校验within
       // 不能校验(execution,call,get,set),面对无法校验的表达式,直接返回true
       return pointcutExpression.couldMatchJoinPointsInType(targetClass);
   }

   
   public boolean accurateMatches(Method method) {
       ShadowMatch shadowMatch = pointcutExpression.matchesMethodExecution(method);
       return shadowMatch.alwaysMatches();
   }
相应的对1.0 进行修改
  1. 修改 @Aspect 注解

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Aspect {
        // 表示当前被 Aspect 标记的横切逻辑,被织入类的位置
        String pointcut();
    }
    
  2. 修改对应的 AspectInfo

    public class AspectInfo {
    	// 优先级
        private int orderIndex;
        // Aspect实例
        private DefaultAspect aspectObject;
        // 依据 @Aspect 的值。为其注入对应的 PointcutExpression
        private PointcutLocator pointcutLocator;
    }
    
源码在这!!

https://github.com/zunchang/simpleframework

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/856639.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号