• spring项目中aop的使用


      AOP:是一种面向切面的编程范式,是一种编程思想,旨在通过分离横切关注点,提高模块化,可以跨越对象关注点。Aop的典型应用即spring的事务机制,日志记录。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。主要功能是:日志记录,性能统计,安全控制,事务处理,异常处理等等;主要的意图是:将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。

      AspectJ和Spring AOP 是AOP的两种实现方案,Aspectj是aop的java实现方案,是一种编译期的用注解形式实现的AOP;Spring aop是aop实现方案的一种,它支持在运行期基于动态代理的方式将aspect织入目标代码中来实现aop,其中动态代理有两种方式(jdk动态代理和cglib动态代理),这里不展开说。这里有几个概念,需要正确理解:

      joinPoint:连接点。在spring中只支持方法连接点,连接点指的是可以使用advice(增强)的地方,例如一个类中有5个方法,那么这5个方法,那么这5个方法都可以是连接点。

      pointcut:切点。可理解为实实在在的连接点,即切入advice(增强)的点。例如一个类中有5个方法,其中有3个方法(连接点)需要织入advice(增强),那么这3个需要织入advice的连接点就是切点。

      advice:增强。实际中想要添加的功能,如日志、权限校验。

      advisor:切面。由切点和增强相结合而成,定义增强应用到哪些切点上。

      Spring支持AspectJ的注解式切面编程。使用方式如下:

      (1)使用@Aspect声明是一个切面

      (2)使用@After、@Before、@Around定义增强(advice),可以直接将拦截规则作为参数(pointcut),其中@Around可以控制目标方法是否执行,并且改变返回结果。

      (3)为了使切点复用,可以使用@PointCut专门定义拦截规则,拦截规则方式有两种:基于注解拦截和基于方法规则拦截,其中注解式拦截能够很好的控制拦截粒度和获取丰富的信息,Spring本身在处理事务和数据缓存也是使用此种方式的拦截。

      spring-aop使用demo如下:

      1、pom.xml,加入以下依赖

    <dependency>
              <groupId>org.springframework</groupId>
              <artifactId>spring-aop</artifactId>
              <version>4.2.5.RELEASE</version>
          </dependency>
          <dependency>
              <groupId>org.aspectj</groupId>
              <artifactId>aspectjrt</artifactId>
              <version>1.7.4</version>
          </dependency>
          <dependency>
              <groupId>org.aspectj</groupId>
              <artifactId>aspectjweaver</artifactId>
              <version>1.8.10</version>
          </dependency>

      2、自定义一个注解,作为拦截规则

      

    package powerx.io;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Mylog {
    
        String level() default "info";
    }

      3、编写功能类

      

    package powerx.io;
    
    import org.springframework.stereotype.Service;
    
    @Service
    public class UserService {
    
        @Mylog(level="debug")
        public void add() {
            System.out.println("添加用户");
        }
        
        @Mylog
        public void find() {
            System.out.println("查看用户");
        }
    }
    package powerx.io;
    
    import org.springframework.stereotype.Service;
    
    @Service
    public class StudentService {
    
        public void add() {
            System.out.println("添加student");
        }
        
        @Mylog(level="debug")
        public Object update(String name) {
            System.out.println("更新student");
            return "更新成功";
        }
    }

      4、切面

    package powerx.io;
    
    import java.lang.reflect.Method;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    import org.aspectj.lang.reflect.MethodSignature;
    import org.springframework.stereotype.Component;
    
    @Aspect
    @Component
    public class LogAspect {
    
        @Pointcut("@annotation(powerx.io.Mylog)")
        public void annotationPointCut() {};
        
        @After("annotationPointCut()")
        public void after(JoinPoint joinPoint) {
            MethodSignature ms = (MethodSignature) joinPoint.getSignature();
            Method method = ms.getMethod();
            Mylog mylog = method.getAnnotation(Mylog.class);
            System.out.println("日志等级"+ mylog.level()+ "注解式拦截");
        }
        
        @Before("execution(* powerx.io.StudentService.*(..))")
        public void before(JoinPoint joinPoint) {
            MethodSignature ms = (MethodSignature) joinPoint.getSignature();
            Method method = ms.getMethod();
            System.out.println("方法规则拦截" + method.getName());
        }
        
        @Around("@annotation(powerx.io.Mylog)&&execution(* powerx.io.StudentService.*(..))")
        public Object around(ProceedingJoinPoint  joinPoint) {
            Object result = null; 
            Object[] obs = joinPoint.getArgs();
            if(obs != null && obs.length >0) {
                String name = (String) obs[0];
                if("zhangsan".equals(name)) {
                    try {
                        result = joinPoint.proceed();
                    } catch (Throwable e) {
                        e.printStackTrace();
                    }
                }else {
                    result =  "只有张三才允许修改";
                }
            }
            return result;
        }
    }

      5、java配置

    package powerx.io;
    
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.EnableAspectJAutoProxy;
    
    @Configuration
    @ComponentScan("powerx.io")
    @EnableAspectJAutoProxy//启动Spring对AspectJ的支持
    public class JavaConfig {
    
    }

      6、主类

    package powerx.io;
    
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    
    public class Main {
    
        public static void main(String[] args) {
            AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(JavaConfig.class);
            UserService us = ac.getBean(UserService.class);
            us.add();
            us.find();
            System.out.println("------------------------");
            StudentService ss = ac.getBean(StudentService.class);
            ss.add();
            Object ob = ss.update("zhangsan");
            System.out.println(ob);
            System.out.println("------------------------");
            Object ob2 = ss.update("lisi");
            System.out.println(ob2);
            ac.close();
        }
    }

      运行主类,控制台显示如下:

  • 相关阅读:
    Idea快捷键
    基于LinkedHashMap实现一个基于LRU算法的缓存设计
    SpringBoot整合Mybatis
    MyBatis Generator自动生成代码
    java.sql.SQLException: The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more
    Dubbo的异步调用
    Jackson的ObjectMapper的简单用法及语法
    mysql实例代码
    6. Z 字形变换
    13. 罗马数字转整数
  • 原文地址:https://www.cnblogs.com/hhhshct/p/9450660.html
Copyright © 2020-2023  润新知