zoukankan      html  css  js  c++  java
  • 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();
        }
    }

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

  • 相关阅读:
    TextBox 只有下划线
    can't find web control library(web控件库)
    DropDownListSalesAC”有一个无效 SelectedValue,因为它不在项目列表中。
    IDE、SATA、SCSI、SAS、FC、SSD 硬盘类型
    如何打印1px表格
    CSS控制打印 分页
    Virtual Server could not open its emulated Ethernet switch driver. To fix this problem, reenable the Virtual Server Emulated Et
    Xml中SelectSingleNode方法中的xpath用法
    热带水果莫入冰箱?水果存放冰箱大法
    探索Asp.net的Postback机制
  • 原文地址:https://www.cnblogs.com/hhhshct/p/9450660.html
Copyright © 2011-2022 走看看