Spring_AOP切面

版权声明:Unruly https://blog.csdn.net/weixin_41660948/article/details/86606667

一、声明式:Spring_OOP和AOP

在这里插入图片描述

使用maven引入:AOP需要在IOC的基础上进行添加
<dependencies>
  	<!-- 第一个会为程序引入基础的IOC和AOP核心包,第二个需要单独添加 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.2.3.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.8.10</version>
    </dependency>
</dependencies>

1、OOP和AOP的关系

AOP: aspect oriented programming 面向切面编程 (处理横向)

OOP: obkect orented programming 面向对象编程 (处理纵向)

  1. OOP和AOP的关系,互为补充。
  2. OOP和AOP没有谁厉害,谁不厉害。
  3. 不能说AOP是OOP的替代品。
  4. 无代码侵入性(即不需要修改原有的代码)。
  5. 实现原理:代理模式(代理)。

2、具体什么是AOP

面向切面编程,指扩展功能不修改源代码,将功能代码从业务逻辑代码中分离出来。

主要功能: 日志纪录、性能统计、安全控制、事务处理、异常处理等等。。

  1. 本质上就是方法拦截;相当于拦截器。
  2. 能够在方法执行之前,或者方法执行之后,自动完成某些事情(执行某些代码)。
  3. 拦截到方法以后,要做什么事情。(增强、通知、advice
  4. 哪些方法会被拦截(即拦截的面有多大)

AOP特点: 采用横向抽取机制,代替传统纵向继承体系重复性代码,从而能更好的对方法进行扩展、复用、增加了灵活性。

织入: weaving(把通知和拦截的目标对象组织起来的过程)
说白了就是在什么地方什么方法进行了什么操作的过程。

连接点: joinpoint(连接点可以是调用方法时、抛出异常时、甚至修改字段时。)

切入点: pointcut(说白了就是在哪些包下的哪些类的哪些方法,会被拦截。)

通知: advice(在什么时候拦截,拦截后做什么事情)

切面: aspect(切入点和通知的结合 、形成切面 – 注意引入委托类)

3、Spring_expression表达式

expression: 表达式,下面的是表达式编写语法规则:

execution(访问修饰符 返回值类型 方法名(参数列表)声明抛出异常的类型)

execution(public * add(*) )

注意:

  1. 返回值类型、方法名、参数是不可以省略的组成部分。
  2. 省略不写的部分,表示不做要求。
  3. 可以带上包名,对指定的包下的指定类进行拦截;方法名也可以使用通配符
    execution(* com.dao.*.add*(..) )
  4. 可以对包下的子包进行拦截,用两个点表示。
    execution(* com.dao..*.*(..))
    在这里插入图片描述

注意:注意理解环绕通知;理解了环绕通知,也就知道了其他通知;其他类型的通知使用JoinPoint对象
在这里插入图片描述

二、注解型AOP

1.注解和xml的区别:

​ — XML AOP配置方式为Spring自带的方式。

​ — 注解 AOP配置方式为Spring引用Aspect。

<!-- 必须开启Aspectj的支持,并且扫描该aop包 -->
<context:component-scan base-package="com.dao,com.biz,com.advice"/>
<aop:aspectj-autoproxy/>
package aop;

import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

/**
 * 描述:用于日志切面记录
 * @author Unruly
 * @ClassName LogAop
 * @create 2019-01-21 14:40
 */
@Aspect
@Component
public class LogImplAop {
    private static Logger logger = Logger.getLogger(LogImplAop.class);

    @Around("execution(* service..*.*(..))")
    public Object around(ProceedingJoinPoint proceed) {
        logger.info("程序执行开始 -------");
        Object[] obj = proceed.getArgs(); 
        for (Object anObj : obj) {
            logger.info("参数:" + anObj);
        }
        Object result = null;
        try {
            logger.debug("目标类:" + proceed.getTarget());
            logger.debug("方法名:" + proceed.getSignature().getName());
            result = proceed.proceed(obj);   
            logger.debug("返回值:"+result);
        } catch (Throwable e) {
            logger.error("发生异常、错误信息:" + e.getMessage());
        } finally {
            logger.info("程序执行结束 -------");
            logger.info("\n");
        }
        return result;
    }
}

2.注解方式进行AOP切面编程总结:

	/*
	 * 	
	 * 	1.切面类需要添加两个注解
	 * 		@Aspect		: 表示为AOP类
	 *  	@Component	: 将此类交给Spring托管。
	 *
	 *  2.配置文件开启注解扫描,和对@AspectJ的支持。
	 *  	<aop:aspectj-autoproxy/>	// @AspectJ支持	
	 *  	<context:component-scan base-package="biz,advice"/>
	 *  
	 *  环绕通知:重点理解包含(前置、后置、异常、最终);
	 *  1.环绕通知因为包含全面使用ProceedingJoinPoint对象,其余使用JoinPoint对象;
	 *  
	 * 	2.proceed()方法表示放行方法,此方法底层采用动态代理,实际上表示的为我们拦截到的方法。
	 * 	(说白了就是你拦截到的方法就是这个方法,只是方法名字换了而已。)
	 * 
	 *  3.获取方法参数Object [] result = proceed.getArgs();
	 *  4.有参数则将获取的参数传入proceed(result);
	 * 	
	 *  5.环绕通知的组成:
	 *  	在调用proceed()之前执行的操作 -- 前置通知	
	 *  	在调用proceed()之后执行的操作 -- 后置通知	(try)
	 *  	在调用proceed()后执行发生异常	-- 异常通知	(catch)
	 *  	在调用proceed()后包含在最终块	-- 最终通知	(finally)
	 *  
	 *  还可以使用@Pointcut注解添加到类上定义一个全局的切入点
	 *  @Pointcut("execution(* aop.dao.BillDao.*(..))")
	 *	public void PointCut(){}
	 *
	 *  其余比如:
	 *  -- 前置
	 *  @Before("execution(PointCut())")	
	 *  public void before(){}
	 *  
	 *  -- 后置
	 *  @After("execution(PointCut())")
	 *  public void after(){}
	 *  
	 *  -- 后置返回
	 *  @AfterReturning(pointcut = "PointCut()",returning = "result")
   *	public void AfterReturning(JoinPoint point,Object result){}
   *
   *	-- 异常
   *	@AfterThrowing(pointcut = "PointCut()",throwing = "e")
   *	public void AfterThrowing(JoinPoint point,RuntimeException e){}
	 */

SpringAOP可能出现的错误!

  1. execution表达式写错了。
  2. 配置文件忘记扫描aop包,忘记加<aop:aspectj-autoproxy/>
  3. 如果切入点没有实现接口使用cglib库动态代理,<aop:aspectj-autoproxy proxy-target-class=“true”/>

猜你喜欢

转载自blog.csdn.net/weixin_41660948/article/details/86606667