zoukankan      html  css  js  c++  java
  • 了解AOP以及实现方式

    AOP是什么?

    面向切面编程,把那些与业务无关,却为业务模块所共同调用的逻辑封装成一个可重的模块,即切面
    使用"横切"技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点

    为什么使用AOP?

    如果说面向对象编程是关注将需求功能划分为不同的并且相对独立,封装良好的类,并让它们有着属于自己的行为,依靠继承和多态等来定义彼此的关系的话;那么面向切面编程则是希望能够将通用需求功能从不相关的类当中分离出来,能够使得很多类共享一个行为,一旦发生变化,不必修改很多类,而只需要修改这个行为即可。

    如下,有两个方法分别为mul和div,这两个方法的内容代码大多数是重复的,则我们可以抽离一个新的方法

    package com.zzj.calculatar.service;
    import org.springframework.stereotype.Service;
    
    @Service
    public class CalculatorService implements ICalculatorService{
    
        @Override
        public int mul(int a, int b) {
            System.out.println("The mul method begins.");
            System.out.println("The mul method args:["+a+","+b+"]");
            return a*b;
        }
    
        @Override
        public int div(int a, int b) {
            System.out.println("The div method begins.");
            System.out.println("The div method args:["+a+","+b+"]");
            return a/b;
        }
        
    }

    新的方法如下:

    @Service
    public class CalculatorService implements ICalculatorService{
    
        @Override
        public int mul(int a, int b) {
            t("mul", a, b);
            return a*b;
        }
    
        @Override
        public int div(int a, int b) {
            t("div", a, b);
            return a/b;
        }
        
        private void t(String methodName,int a,int b){
            System.out.println("The"+methodName+"method begins.");
            System.out.println("The"+methodName+"method args:["+a+","+b+"]");
        }
        
    }

    AOP的切面化就体现在此,具体的AOP实现方式有:注解和XML配置

    package com.zzj.calculatar.service;
    import org.springframework.stereotype.Service;
    
    @Service
    public class CalculatorService implements ICalculatorService{
    
        @Override
        public int mul(int a, int b) {
            return a*b;
        }
    
        @Override
        public int div(int a, int b) {
            return a/b;
        }
        
    }

    注解方式实现AOP:

    package com.zzj.aspect;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    import org.springframework.core.annotation.Order;
    import org.springframework.stereotype.Component;
    
    
    @Order(1)//切片执行顺序,默认为字典顺序
    @Aspect
    @Component
    public class CalculatorAspect {
    
            //提取表达式
        @Pointcut("execution(public int com.zzj.calculatar.service.CalculatorService.*(..))")
        public void pointCut(){
            
        }
        
        @Around(value="pointCut()")
        public Object around(ProceedingJoinPoint joinPoint){
            Object result = null;
            Object target = joinPoint.getTarget();//目标对象
            String methodName = joinPoint.getSignature().getName();
            Object[] params = joinPoint.getArgs();
            
            try{
                try{
                    //前置增强
                    System.out.println(target.getClass().getName()+": The "+methodName+" method begins.");
                    System.out.println(target.getClass().getName()+": Parameters of the "+methodName+"method: ["+params[0]+","+params[1]+"]");
                    //执行目标对象内的方法
                    result = joinPoint.proceed();
                }finally{
                    //后置增强
                    System.out.println(target.getClass().getName()+":The "+methodName+" method ends.");
                }
                //返回增强
                System.out.println(target.getClass().getName()+":Result of the "+methodName+" method:"+result);
            }catch (Throwable e) {
                System.out.println(target.getClass().getName()+":Exception of the method "+methodName+": "+e);
            }
            return result;
        }
        
    }    
    <!--XML代码-->
    <context:component-scan base-package="com.zzj"></context:component-scan>
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

    XML配置方式实现AOP(不需要注解,将注解放在XML中):

    package com.zzj.aspect;
    import org.aspectj.lang.ProceedingJoinPoint;
    public class CalculatorAspect {
        public Object around(ProceedingJoinPoint joinPoint){
            Object result = null;
            Object target = joinPoint.getTarget();//目标对象
            String methodName = joinPoint.getSignature().getName();
            Object[] params = joinPoint.getArgs();
            
            try{
                try{
                    //前置增强
                    System.out.println(target.getClass().getName()+": The "+methodName+" method begins.");
                    System.out.println(target.getClass().getName()+": Parameters of the "+methodName+"method: ["+params[0]+","+params[1]+"]");
                    //执行目标对象内的方法
                    result = joinPoint.proceed();
                }finally{
                    //后置增强
                    System.out.println(target.getClass().getName()+":The "+methodName+" method ends.");
                }
                //返回增强
                System.out.println(target.getClass().getName()+":Result of the "+methodName+" method:"+result);
            }catch (Throwable e) {
                System.out.println(target.getClass().getName()+":Exception of the method "+methodName+": "+e);
            }
            return result;
        }
    }
    <!--扫描-->
    <context:component-scan base-package="com.zzj"></context:component-scan>
    <!--获取aspect类-->
    <bean id="calculatorAspect" class="com.zzj.aspect.CalculatorAspect"></bean>
    
    <aop:config>
            <!--提取表达式-->
        <aop:pointcut expression="execution(public int com.zzj.calculatar.service.CalculatorService.*(..))" id="pointCut"/>
            <!--环绕增强-->
        <aop:aspect ref="calculatorAspect" order="1">
            <aop:around method="around" pointcut-ref="pointCut"/>
        </aop:aspect>
    </aop:config>

    测试类:

    package com.zzj.test;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import com.zzj.calculatar.service.ICalculatorService;
    
    public class Test {
    
        public static void main(String[] args){
            
            ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");
            ICalculatorService calculatorService = applicationContext.getBean(ICalculatorService.class);
            System.out.println(calculatorService.getClass());//当有代理类时,获取的代理对象
            System.out.println(calculatorService.div(1,1));
            applicationContext.close();
            
        }
        
    }

    测试结果:

  • 相关阅读:
    SpringMVC Failed to instantiate [java.util.List]: Specified class is an interface
    github上项目直接在浏览器页面像VS Code一样查看代码
    springboot+dubbo整合swagger-ui+swagger-dubbo
    petalinux非离线模式build卡死在u-boot编译问题
    SystemC使用示例
    使用chisel做数字电路开发的Hello World
    lmgrd在Linux系统上的配置
    FFmpeg libswscale源码分析3-scale滤镜源码分析
    FFmpeg libswscale源码分析2-转码命令行与滤镜图
    FFmpeg libswscale源码分析1-API介绍
  • 原文地址:https://www.cnblogs.com/yimengxianzhi/p/12261804.html
Copyright © 2011-2022 走看看