Spring深入浅出(四)AOP面向切面

面向切面编程--AOP

AOP(Aspect Oriented Programming),程序员称之为面向切面编程,是Spring框架除了IOC之外的另一个核心概念。

AOP是对OOP(面向对象编程)的一个补充,在代码运行过程中,动态地将代码切入到某个类的指定方法、指定位置上。也就是面向切面编程。

AOP的优点

1.降低模块之间的耦合度。
2.使系统容易扩展。
3.更好的代码复用。
4.非业务代码更加集中,不分散,便于统一管理。
5.业务代码更简洁纯粹,没有其他代码的影响。

AOP的几个概念

切面:横切关注点被模块化的特殊对象。

通知:切面对象完成的工作。

目标:被通知的对象,即被横切的对象。

代理:切面通知目标混合之后的内容。 

连接点:程序要执行的某个特定位置。

切点:AOP通过切点定位到连接点。

AOP增强

Weaving(织入):对方法进行增强

(1)前置增强(BeforeAdvice):在目标方法前调用。

(2)后置增强(AfterAdvice):在目标方法后调用。

(3)环绕增强(AroundAdvice):将 Before 和 After ,甚至抛出增强和返回增强合到一起。

(4)返回增强(AfterReturningAdvice):在方法返回结果后执行,该增强可以接收到目标方法返回结果。

(5)抛出增强(AfterThrowingAdvice):在目标方法抛出对应的类型后执行,可以接收到对应的异常信息。

Introduction(引入):对类进行增强

  引入增强(DeclareParentsAdvice):想让程序在运行的时候动态去实现某个接口,需要引入增强。

代码解释

//创建一个借口
public interface Cal {
    public int add(int num1,int num2);
    public int sub(int num1,int num2);
    public int mul(int num1,int num2);
    public int div(int num1,int num2);
}

//创建一个接口的实现类
@Component public class CalImpl implements Cal{ @Override public int add(int num1, int num2) { // TODO Auto-generated method stub int result = num1+num2; return result; } @Override public int sub(int num1, int num2) { // TODO Auto-generated method stub int result = num1-num2; return result; } @Override public int mul(int num1, int num2) { // TODO Auto-generated method stub int result = num1*num2; return result; } @Override public int div(int num1, int num2) { // TODO Auto-generated method stub int result = num1/num2; return result; } }

创建一个切面类

@Aspect  //表示切面类
@Component    //表示将该类注入到IOC容器
public class LoggerAspect {

    @Before("execution(public int com.test.aspect.CalImpl.*(..))")
    public void before(JoinPoint joinPoint){
        //获取方法名
        String name = joinPoint.getSignature().getName();
        //获取参数列表
        String args = Arrays.toString(joinPoint.getArgs());
        System.out.println(name+"的参数是:"+args);
    }

    @After("execution(public int com.test.aspect.CalImpl.*(..))")
    public void after(JoinPoint joinPoint){
        //获取方法名
        String name = joinPoint.getSignature().getName();
        System.out.println(name+"方法结束");
    }

    @AfterReturning(value="execution(public int com.test.aspect.CalImpl.*(..))",returning="result")
    public void afterReturn(JoinPoint joinPoint,Object result){
        //获取方法名
        String name = joinPoint.getSignature().getName();
        System.out.println(name+"方法的结果是"+result);
    }

    @AfterThrowing(value="execution(public int com.test.aspect.CalImpl.*(..))",throwing="ex")
    public void afterThrowing(JoinPoint joinPoint,Exception ex){
        //获取方法名
        String name = joinPoint.getSignature().getName();
        System.out.println(name+"方法抛出异常:"+ex);
    }

}

注解的解释:

1.@Before:表示方法执行的时机。

2.execution(public int com.test.aspect.CalImpl.*(..)):表示切入点是com.southwind.aspect包下CalImpl类中的所有方法。

XML注解配置 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop
     http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/context
     http://www.springframework.org/schema/context/spring-context-4.0.xsd"
> <!-- 自动扫描 --> <context:component-scan base-package="com.test.aspect"/> <!-- 使Aspect注解生效,为目标类自动生成代理对象 --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans>

 XML不使用注解的方式

<!--将切面交给spring管理-->
<bean id="myAspect" class="com.test.ProductService.MyAspect"></bean> 
<aop:config ref="myAspect">
        <!--切入点-->
        <aop:pointcut id="logrPoint"
            expression=
            "execution(* com.service.ProductService.*(..)) "/>
             
        <aop:aspect id="logAspect" ref="logAspect">
            <aop:after pointcut-ref="logrPoint" method="log"/>
        </aop:aspect>
  </aop:config>

AOP的通知类型

在 Spring 中共有 5 类通知类型,用来分别表示切面在不同时候要做的工作。

  • 前置通知(Before Advice):在切入点选择的连接点处的方法之前执行的通知,该通知不影响正常程序执行流程(除非该通知抛出异常,该异常将中断当前方法链的执行而返回)。

  • 后置通知(After Advice):在切入点选择的连接点处的方法之后执行的通知(无论方法执行是否成功都会被调用)。

  • 后置返回通知(After returning Advice):在切入点选择的连接点处的方法正常执行完毕时执行的通知,必须是连接点处的方法没抛出任何异常正常返回时才调用。

  • 后置异常通知(After throwing Advice): 在切入点选择的连接点处的方法抛出异常返回时执行的通知,必须是连接点处的方法抛出任何异常返回时才调用异常通知。

  • 环绕通知(Around Advices):环绕着在切入点选择的连接点处的方法所执行的通知,环绕通知可以在方法调用之前和之后自定义任何行为,并且可以决定是否执行连接点处的方法、替换返回值、抛出异常等等。

原文地址:https://www.cnblogs.com/JiangLai/p/9566051.html