美文网首页
SpringAOP学习中

SpringAOP学习中

作者: 取名废同学 | 来源:发表于2018-11-21 17:44 被阅读0次

    springAOP面向切面编程,非编程语言,是编程范式,只能解决特定问题,是OOP的补充而非替代。

    初衷:解决代码重复性问题;
    关注点分离(水平分离:分展示层、服务层、持久层;垂直分离:按功能模块;切面分离:分离功能性需求和非功能性需求)

    使用AOP的好处:
    集中处理某一关注点/横切逻辑
    方便添加/删除关注点
    侵入性少,增强代码可读性与可维护性

    AOP的应用场景:
    权限控制、缓存控制、事务控制、审计日志、性能监控、分布式追踪、异常处理。

    支持AOP的编程语言:
    JAVA .net python c/c++... ruby...

    例如:举一个场景的例子,添加或删除的操作必须由管理员完成,这是两个方法,用普通方法,是添加和删除方法中,要先加【判断是否为管理员的代码】,运用AOP的方式,则是把【判断是管理员】的代码切出来

    SpringAOP的使用方式
    1、XML配置
    2、注解方式在java文件中
    @Aspect:在类前,用于说明该类是切面的配置的类
    @Pointcut:描述在哪些类/哪些方法植入你的代码
    Advice:你想在以上方法的什么时候进行植入,之前?之后?
    @Component:让这个类给spring托管

    一、切面表达式Pointcut expression:
    designators:指示器,通过什么方式去匹配想要的java的类的方法


    image.png

    wildcards:通配符 (*:任意数量; +:匹配指定类及子类; 。。:匹配任意数的子包或参数
    operators:运算符,组合(&&;||;!)

    (一)designators:指示器
    1、within表达式:限定在哪个类或哪个包


    image.png

    2、对象匹配:


    image.png

    常默认this和target一样

    3、参数匹配:
    两种方法:定义execution方法(要返回值啥的,麻烦)和args方法


    4、注解匹配:4个,一个是匹配方法级别,2个匹配类级别,一个匹配参数级别


    image.png

    1匹配注解级别,2、3匹配类级别,一般默认相同;4匹配方法级别

    5、execution表达式:



    修饰符pattern
    返回值类型pattern
    描述包名
    描述方法名(描述参数)
    匹配方法抛出异常
    (1 3 5可省略)

    二、Advice注解
    @Before:前置通知,方法前执行
    @After(finally):后置通知,方法执行完之后
    @AfterReturning:返回通知,成功执行之后,有返回值
    @AfterThrowing:异常通知,抛出异常之后
    @Around:环绕通知,万能注解


    image.png

    SpringAOP实现原理:
    aop织入时机:
    1、编译期(AspectJ)
    2、类加载时(AspectJ 5+)
    3、运行时(Spring AOP)

    运行时织入:代理对象
    【代理:
    静态代理:
    动态代理:基于接口代理/基于继承代理】

    设计模式:代理模式、责任链模式
    一、代理模式(静态代理)
    委托类和代理类实现同一接口,并写同一个方法,代理类中有委托类的一个实例,在其方法中,还是用委托类的实例来完成这个方法。


    image.png

    缺点:重复方法;

    二、动态代理:
    两类实现:基于接口/基于继承代理
    两类实现代表:JDK代理与Cglib代理
    1、JDK代理:
    通过类java.lang.reflect.Proxy动态生成代理类
    代理类需要实现InvocationHandler接口(接口有invoke方法,代理类中还需引用委托类对象)
    jdk代理只能基于接口进行动态代理
    优点:如果有多个方法,也无需在代理类中重写,只需在接口中写
    2、JDK代理源码解析


    image.png

    方法,去调用其他3个方法,
    最后生成字节码用java反射生成实例

    3、Cglib动态代理:通过继承的方式来实现代理


    image.png

    4、spring对两种实现的选择:
    目标对象实现接口,默认采用JDK代理;
    目标对象无实现接口,采用cglib代理;
    目标对象实现了接口但强制cglib代理,则cglib


    二、责任链模式:
    多个AOP链式调用 ,


    1、抽象类Handler中有HanlerProcess()抽象方法,需要实现类实现,同时实现类又组合了Handler,通过这种successor的判断来实现链式调用


    image.png

    successor用于判断接下来还有没有人去处理。



    对象存在,则接下来调用链式的execute()

    2、创建多个继承Hanler抽象类的类,然后在各自的handlerProcessor()执行各自的业务逻辑

    2、客户端中设置多个类的调用关系,只调用第一个的execute()
    handlerA.setSuccessor(handlerB);
    handlerB.setSuccessor(handlerC);
    hanlerA.execute()

    所有代码:
    Hanler抽象类:

    public abstract class Handler {
         private Handler successor;
    
         public Handler getSuccessor() {
              return successor;
         }
    
         public void setSuccessor(Handler successor) {
              this.successor = successor;
         }
    
         public void execute(){
              handlerProcess();
              if(successor!=null){
                   successor.execute();
              }
         }
    
         protected  abstract  void handlerProcess();
    }
    
    

    客户端Client类,其中有三个内部静态类ABC继承hanler类

    public class Client {
        static class HandlerA extends Handler{
            @Override
            protected void handlerProcess() {
                System.out.println("hanler by a");
            }
        }
    
        static class HandlerB extends Handler{
            @Override
            protected void handlerProcess() {
                System.out.println("hanler by b");
            }
        }
    
        static class HandlerC extends Handler{
            @Override
            protected void handlerProcess() {
                System.out.println("hanler by c");
            }
        }
    
        public static void main(String[] args) {
            Handler handlerA = new HandlerA();
            Handler handlerB = new HandlerB();
            Handler handlerC = new HandlerC();
    
            handlerA.setSuccessor(handlerB);
            handlerB.setSuccessor(handlerC);
            handlerA.execute();
        }
    }
    
    

    缺点:在于必须手动把链式调用的链式关系写出来,比较麻烦。
    所以进行改进,将上面那块进行封装成一个类

    Chain中有一个内部List<handler>,然后把所有的handler存进去,内部实现游标的跳转,不断调用下一个。

    ChainHandler:

    public abstract class ChainHandler {
    
        public void execute(Chain chain){
            handleProcess();
            chain.proceed();//调用下一个游标
        }
        protected abstract void handleProcess();
    }
    
    

    Chain:

    import java.util.List;
    
    public class Chain {
        private List<ChainHandler> handlers;
        private int index=0;
        public Chain(List<ChainHandler> handlers){
            this.handlers=handlers;
        }
        public void proceed(){
            if(index>=handlers.size()){
                return;
            }
            handlers.get(index++).execute(this);
        }
    }
    
    

    ChainClient:

    import java.lang.reflect.Array;
    import java.util.Arrays;
    import java.util.List;
    
    public class ChainClient {
        static class ChainHandlerA extends ChainHandler{
            @Override
            protected void handleProcess() {
                System.out.println("handle by chain a");
            }
        }
        static class ChainHandlerB extends ChainHandler{
            @Override
            protected void handleProcess() {
                System.out.println("handle by chain b");
            }
        }
        static class ChainHandlerC extends ChainHandler{
            @Override
            protected void handleProcess() {
                System.out.println("handle by chain c");
            }
        }
        public static void main(String[] args){
            List<ChainHandler> handlers= Arrays.asList(
                    new ChainHandlerA(),
                    new ChainHandlerB(),
                    new ChainHandlerC()
            );
            Chain chain=new Chain(handlers);
            chain.proceed();
        }
    }
    
    

    springAOP也是使用这种Chain方式,用游标的方式。

    使用springAOP注意事项:
    1、不把重要的业务逻辑放到AOP中处理,容易被忽略,应该放比较通用的业务
    2、无法拦截static、final、private方法
    3、无法拦截内部方法调用

    相关文章

      网友评论

          本文标题:SpringAOP学习中

          本文链接:https://www.haomeiwen.com/subject/zohcqqtx.html