Spring4-2-AOP配置

一.AOP概念

Paste_Image.png
Paste_Image.png

二.AOP术语

Paste_Image.png

三.Spring AOP框架AspectJ配置使用(基于注解的方式)

Paste_Image.png

(1)必要的jar包


Paste_Image.png

(2)在Spring bean的配置文件中加入aop命名空间;
(3)创建计算器接口(包含:增删改查方法)

package lxf.spring.aop.impl;
/**
 * 计算器接口
 * @author lxf
 */
public interface CalculatorInterface {
    //加法
    public int add(int i, int j);
    //减法
    public int sub(int i, int j);
    //乘法
    public int mul(int i, int j);
    //除法
    public int div(int i, int j);
}

(4)创建计算器的实现类

package lxf.spring.aop.impl;
import org.springframework.stereotype.Component;
/**
 * 计算器接口实现类
 * @author lxf
 */
@Component
public class CalculatorImpl implements CalculatorInterface {
    @Override
    public int add(int i, int j) {
        return i+j;
    }
    @Override
    public int sub(int i, int j) {
        return i-j;
    }
    @Override
    public int mul(int i, int j) {
        return i*j;
    }
    @Override
    public int div(int i, int j) {
        // TODO Auto-generated method stub
        return i/j;
    }
}

(5)基于注解的方式配置AspectJ
在Spring配置文件中加入:

        <!-- 扫描lxf.spring.aop.impl下带主键的bean,实例后加入IOC容器 -->
        <context:component-scan base-package="lxf.spring.aop.impl"></context:component-scan>
        <!-- 使AspectJ注解起作用,自动为匹配的类生成代理对象 -->
        <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

(6)把横切关注点的代码抽象到切面的类LogAspect中;

package lxf.spring.aop.impl;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.List;

import javax.naming.spi.DirStateFactory.Result;

import org.aopalliance.intercept.Joinpoint;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
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.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
/**
 * 切面类
 * @author lxf
 */
//使用Order接口指定一个连接点处多个切面的优先级,值越小越优先执行
@Order(2)
//加入Aspect注解,证明是切面类,与配置文件中<aop:aspectj-autoproxy></aop:aspectj-autoproxy>配合
@Aspect
//切面首先是一个iOC容器的bean,使用Component注解的方式加入IOC容器
@Component
public class LogAspect {
    /*
     * 定义一个方法,用于声明切入点表达式,一般地,该方法中再不需要填入其他代码
     * 使用 @Pointcut注解来声明切入点表达式
     * 后面的其他通知直接使用方法名引用该切入点表达式
     */
    @Pointcut("execution(public int lxf.spring.aop.impl.CalculatorInterface.*(..))")
    public void declareJointPointExpression(){}
    
    /*
     * 前置通知:在lxf.spring.aop.impl.CalculatorInterface接口中的每个方法开始执行之前执行一段代码
     * 声明该方法是一个前置通知,在执行目标方法前执行, *代表匹配所有方法,..代表匹配任意参数
     */
    @Before("declareJointPointExpression()")
    public void myBefore(JoinPoint joinPoint)
    {
        String methodName = joinPoint.getSignature().getName();
        List<Object> args = Arrays.asList(joinPoint.getArgs());
        System.out.println("The method begins methodName = " + methodName + ",参数=" + args);
    }
    /**
     * 后置通知:在lxf.spring.aop.impl.CalculatorInterface接口中的每个方法开始执行之后执行一段代码
     * 在目标方法执行之后(无论是否发生异常),执行的通知
     * 在后置通知中不能访问目标方法执行的结果
     */
    @After("declareJointPointExpression()")
    public void myAfter(JoinPoint joinPoint)
    {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("The method end methodName = " + methodName);      
    }
    /**
     * 返回通知:在方法正常结束处执行的代码
     * 是可以访问到方法的返回值的
     */
    @AfterReturning(value="declareJointPointExpression()",returning="result")
    public void myReturn(JoinPoint joinPoint,Object result)
    {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("The method return methodName = " + methodName + "返回值=" + result);      
    }
    /**
     * 异常通知:在目标方法出现异常时会执行的代码
     * 可以访问到异常对象,并且可以指定在出现特定异常时在执行通知的代码
     * @param joinPoint
     * @param ex
     */
    @AfterThrowing(value="declareJointPointExpression()",throwing="ex")
    public void myThrow(JoinPoint joinPoint, Exception ex)
    {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("The method  methodName = " + methodName + "出现了异常=" + ex);    
    }
    /**
     * 环绕通知需要携带ProceedingJoinPoint类型的参数
     * 环绕通知类似于动态代理的全过程,ProceedingJoinPoint类型的参数可以决定是否执行目标方法
     * @param pjd
     
    @Around("execution(* lxf.spring.aop.impl.CalculatorInterface.*(..))")
    public Object myArround(ProceedingJoinPoint pjd)
    {
        Object result = null;
        String methodName = pjd.getSignature().getName();
        List<Object> args = Arrays.asList(pjd.getArgs());
            try {
                //前置通知:
                System.out.println("The method begins methodName = " + methodName + ",参数=" + args);
                //执行目标方法
                result = pjd.proceed(); //执行目标方法,相当于动态代理的method.invoke(target, args);
                //返回通知
                System.out.println("The method return methodName = " + methodName + "返回值=" + result);      
            } catch (Throwable e) {
                //异常通知
                System.out.println("The method  methodName = " + methodName + "出现了异常=" + e);    
                //将异常继续抛出给运行时异常
                throw new RuntimeException(e);
                //e.printStackTrace();
            }
            //后置通知
            System.out.println("The method end methodName = " + methodName);      
            return result;
    }  */
}

输出结果:

com.sun.proxy.$Proxy10
The method begins methodName = add,参数=[4, 2]
The method end methodName = add
The method return methodName = add返回值=6
6
The method begins methodName = div,参数=[4, 2]
The method end methodName = div
The method return methodName = div返回值=2

指定切面优先级

Paste_Image.png

四.Spring AOP基于配置文件的方式配置

(1)应用以上的接口和实现类和切面类,将注解去掉;
(2)Spring的配置文件applicationContext-xml.xml配置

        <!-- 配置计算器实现类bean -->
        <bean id="cal"  class="lxf.spring.aop.xmlconfig.CalculatorImpl"></bean>
        <!-- 配置日志切面bean -->        
        <bean id="logAspect" class="lxf.spring.aop.xmlconfig.LogAspect"></bean>
        <!-- 配置验证切面bean -->
        <bean id="validateAspect" class="lxf.spring.aop.xmlconfig.ValidateAspect"></bean>
        
        <!-- 配置AOP -->
        <aop:config>
            <!-- 配置切点表达式 -->
            <aop:pointcut expression="execution(public int lxf.spring.aop.xmlconfig.CalculatorInterface.*(..))"  id="pointcut" />
            <!-- 配置日志切面通知 -->
            <aop:aspect ref="logAspect" order="2">
                <!-- 前置通知 -->
                <aop:before method="myBefore" pointcut-ref="pointcut"/>
                <!-- 后置通知 -->
                <aop:after method="myAfter" pointcut-ref="pointcut"/>
                <!-- 返回通知 -->
                <aop:after-returning method="myReturn" pointcut-ref="pointcut" returning="result"/>
                <!-- 异常通知 -->
                <aop:after-throwing  method="myThrow" pointcut-ref="pointcut" throwing="ex"/>
            </aop:aspect>
            <!-- 配置验证切面通知 -->
            <aop:aspect ref="validateAspect" order="1">
                <aop:before method="myBefore" pointcut-ref="pointcut"/>
            </aop:aspect>
        </aop:config>
</beans>

代码演示点击

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,139评论 19 139
  • 本章内容: 面向切面编程的基本原理 通过POJO创建切面 使用@AspectJ注解 为AspectJ切面注入依赖 ...
    谢随安阅读 3,233评论 0 9
  • 好名字,包含两个关键字,一个是好,一个是名字。好名字的关键点是通俗易懂,易于传播,包含了一些积极的意义。尤其是做大...
    IT学思想阅读 436评论 0 1
  • :26岁,你看着身边的人都结了婚 婚礼的份子钱逐年递增 春节回家,父母从带你串亲戚 变成了带你去见相亲对象 见了十...
    看书挺好的阅读 295评论 0 0
  • 提起宝马第一时间会想起什么呢? 在古时宝马向来是人心所追求的,因为那个时代,马是迅捷的象征。骑着一匹宝马奔袭在广袤...
    化浊阅读 1,111评论 0 0