简单了解下Spring Aop

一、AOP

AOP:面向切面编程。在开发的时候,有时候我们需要对有些类中的方法添加日志功能或者权限校验等。这些与应用的主要逻辑无关但是又相当重要的功能,被称之为横切关注点。但这些功能又不属于我们类中的业务逻辑,如果特意创建一个实例对象来维护它,势必会带来代码的重复性。为了解决这个问题,spring添加了AOP这个特性,使得业务逻辑与这些横切关注点分离开。

1.术语

  1. 连接点(join point):
    • 是可以插入切面的点,可以被拦截的点。
  2. 切入点(Pointcut):
    • 我们选择只需要增强的连接点,减少切面的范围,切点定义了切面的位置,在何处执行通知。
  3. 通知(Advice):
    • 通知是指切面的功能,定义了切面是什么,何时执行。
  4. 切面(Aspect):
    • 切面是通知和切入点的组合。一个切面代表着:要对切入的点进行什么样的操作,何时执行,以及切面是什么。
  5. 织入(Weaving):
    • 将切面应用到目标对象并创建代理对象的过程。

2.通知类型

  1. 前置通知(Before):MethodBeforeAdvice

    import org.springframework.aop.MethodBeforeAdvice;
    
    public class MyBeforeAdvice implements MethodBeforeAdvice {
        public void before(Method method, Object[] args, Object target) throws Throwable {
            System.out.println("前置通知=======================");
        }
    }
    
  2. 返回通知(After-returning):AfterReturningAdvice

    import org.springframework.aop.AfterReturningAdvice;
    
    public class MyAfterAdvice implements AfterReturningAdvice {
        public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
            System.out.println("后置通知=========");
        }
    }
    
  3. 环绕通知(Around):MethodInterceptor

    import org.aopalliance.intercept.MethodInterceptor;
    import org.aopalliance.intercept.MethodInvocation;
    
    public class MyAroundAdvice implements MethodInterceptor {
        public Object invoke(MethodInvocation invocation) throws Throwable {
            //在执行被代理类方法之前,添加功能
            System.out.println("环绕通知之前=============");
            // 执行被代理类的方法
            Object obj = invocation.proceed();
            //在执行被代理类方法之后
            System.out.println("环绕通知之后=============");
            System.out.println();
            return null;
        }
    }
    
  4. 异常通知(After-throwing):ThrowsAdvice

    注意:类方法名必须为afterThrowing

    import org.springframework.aop.ThrowsAdvice;
    
    public class MyThrowAdvice implements ThrowsAdvice {
        public void afterThrowing(Exception e )throws Throwable {
            System.out.println("抛出异常===========");
        }
    }
    

3.切面类型

  1. Advisor:

    ​ 普通切面,拦截目标类中所有方法。

    <bean id="userDao" class="impl.UserDaoImpl"/>
    <!-- 配置通知类 -->
    <bean id="myBeforeAdvice" class="advice.MyBeforeAdvice"/>
    
    <- 配置代理类 -->
    <bean id="userDaoProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
    	<-- 配置目标类 -->
    	<property name="target" ref="userDao"/>
    	<!-- 配置目标类的接口 -->
    	<property name="proxyInterfaces" value="dao.UserDao"/>
    	<!-- 配置advice类型 -->
    	<property name="interceptorNames" value="myBeforeAdvice"/>
    </bean>
    
  2. PointcutAdvisor:

    ​ 带有切点的切面,只拦截需要增强的方法。

    <!-- 配置通知类 -->
    <bean id="myBeforeAdvice" class="advice.MyBeforeAdvice"/>
    <!-- 配置正则表达式的PointcutAdvisor -->
    <bean id="advisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
        <!-- 配置advice -->
        <property name="advice" ref="myBeforeAdvice"/>
        <!-- 配置要拦截的方法,使用正则表达式 -->
        <property name="patterns" value=".*find*"/>
    </bean>
    <bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="target" ref="customerDao"/>
        <property name="proxyTargetClass" value="true"/>
        <property name="interceptorNames" value="advisor"/>
    </bean>
    
  3. 注意:Spring Aop是基于代理来实现的,jdk代理和CGLib。jdk代理需要传入目标类的接口,不支持没有接口的类。所以就需要CGLib了,CGLib支持不带接口的类。在配置时,选择 proxyInterfaces,使用jdk代理;选择proxyTargetClass,使用CGLib代理。

4.AspectJ

使用传统的spring Aop ,必须为每个目标类创建一个ProxyFactoryBean,在其中配置目标类、目标类的接口、通知类。如果横切关注点有很多的话,创建的bean也会随之增多,这大大增加了代码量。从Spring2.0后,Spring引进了AspectJ 这个框架,其java注解大大地简化了我们使用Aop的复杂度。

  1. 环境配置:需要导入的jar包

    • 在maven下,导入以下4个jar包

      <dependency>
          <groupId>aopalliance</groupId>
          <artifactId>aopalliance</artifactId>
          <version>1.0</version>
      </dependency>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-aop</artifactId>
          <version>4.2.4.RELEASE</version>
      </dependency>
      
      <dependency>
          <groupId>org.aspectj</groupId>
          <artifactId>aspectjweaver</artifactId>
          <version>1.8.13</version>
      </dependency>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-aspects</artifactId>
          <version>4.2.4.RELEASE</version>
      </dependency>
      
  2. 定义切面:

    要点:

    • @Aspect:将一个POJO类定义为切面类
    • @EnableAspectJAutoProxy:开启自动代理,它会为带有@Aspect的切面类创建一个代理。这样我们就不用去配置代理需要的目标类,接口和通知类,是CGLib还是jdk代理,这些自动代理全部帮助我们解决了。
    • @Pointcut:定义一个切点,一个切点由pointcut表达式和pointcut签名组成。
      • 在Advice注解中使用pointcut签名即可使用切点。
      • 语法格式:@pointcut(value = “execution(修饰符 返回类型 全限定类名.方法名(参数类型))”)
      • 在execution()中,使用*代表全部,在方法名()中使用…代表任意参数,即method(…)。
      • 使用 || && ^ 来添加bean或者切面的表达式。
    @Aspect
    @EnableAspectJAutoProxy
    public class TrackCounter {
        private Map<Integer, Integer> trackCounts = new HashMap<Integer, Integer>();
        @Pointcut(value = "execution(* com.sean.soudSystem.CompactDisc.playTrack(int)) && args(trackNumber)")
        public void TrackCounter(int trackNumber) { }
    
        @Before("TrackCounter(trackNumber)")
        public void countTrack(int trackNumber) {
            int currentCount = getPlayCount(trackNumber);
            trackCounts.put(trackNumber, currentCount + 1);
        }
    
        public int getPlayCount(int trackNumber) {
            return trackCounts.containsKey(trackNumber) ? trackCounts.get(trackNumber) : 0;
        }
    
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值