spring--基础--06--Spring框架的AOP

spring–基础–06–Spring框架的AOP


代码地址

https://gitee.com/DanShenGuiZu/learnDemo.git

1、介绍

  1. 面向切面编程
  2. 当执行一个方法时,可以在方法执行之前或之后添加额外的功能。

2、AOP术语

  1. @Aspec:声明这个类是切面
  2. Joinpoint(连接点):
    1. 程序能够应用通知的一个"时机",这些"时机"就是连接点,例如方法被调用时、异常被抛出时等等。
    2. 可以理解为被aop拦截的类或者方法就是连接点。
  3. Advice(通知):这是实际行动之前或之后执行的方法。
  4. Pointcut(切点):这是一组一个或多个切点,也就是触发切面的拦截条件
  5. Introduction:引用允许你添加新方法或属性到现有的类中。
  6. Target object:一个或者多个方面所通知的对象,这个对象永远是一个被代理对象。也称为被通知对象。
  7. Weaving:把切面连接到其它的应用程序类型或者对象上,并创建一个被通知的对象。这些可以在编译时,类加载时和运行时完成。
  8. AOP代理(AOP Proxy)
  9. 在Spring AOP中有两种代理方式,JDK动态代理和CGLIB代理。默认情况下,Target Object实现了接口时,则采用JDK动态代理;反之,采用CGLIB代理。
  10. 织入(Weaving)把切面应用到目标对象来创建新的代理对象的过程,织入一般发生在如下几个时机:
    1. 编译时:当一个类文件被编译时进行织入,这需要特殊的编译器才能做到,例如AspectJ的织入编译器;
    2. 类加载时:使用特殊的ClassLoader在目标类被加载到程序之前增强类的字节代码;
    3. 运行时:切面在运行的某个时刻被织入,SpringAOP就是以这种方式织入切面的,原理是使用了JDK的动态代理

3、通知的类型

  1. @Before前置通知(Beforeadvice)
    1. 在某连接点(JoinPoint)——核心代码(类或者方法)之前执行的通知
    2. 这个通知不能阻止连接点前的执行。
      1. @Before注解的方法入参不能传ProceedingJoinPoint,而只能传入JoinPoint。要知道从aop走到核心代码就是通过调用ProceedingJionPoint的proceed()方法。而JoinPoint没有这个方法。
      2. Proceedingjoinpoint继承了JoinPoint。是在JoinPoint的基础上暴露出proceed这个方法。
      3. proceed很重要,这个是aop代理链执行的方法。暴露出这个方法,就能支持aop:around这种切面(而其他的几种切面只需要用到JoinPoint,这跟切面类型有关),能决定是否走代理链还是走自己拦截的其他逻辑。
      4. 建议看一下JdkDynamicAopProxy的invoke方法,了解一下代理链的执行原理。这样你就能明白proceed方法的重要性。
  2. @After后通知(Afteradvice):
    1. 当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。
  3. @AfterReturning返回后通知(Afterreturnadvice):
    1. 在某连接点正常完成后执行的通知,不包括抛出异常的情况。
  4. @Around环绕通知(Aroundadvice):
    1. 方法执行前或者执行后的通知
    2. 这个注解的方法入参传的是ProceedingJionPointpjp,可以决定当前线程能否进入核心方法中。
      1. 通过调用pjp.proceed()
  5. @AfterThrowing抛出异常后通知(Afterthrowingadvice):
    1. 在方法抛出异常退出时执行的通知。

4、advice(通知)注解的执行先后顺序

在这里插入图片描述

4.1、测试配置

在这里插入图片描述

在这里插入图片描述

4.2、测试正常数据

在这里插入图片描述

在这里插入图片描述

4.3、测试异常数据

在这里插入图片描述

在这里插入图片描述

5、实现方式

  1. 基于配置的XML来实现
  2. 基于@Aspect来实现

5.1、基于配置的XML来实现

<!-- aop -->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

<?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"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
	http://www.springframework.org/schema/aop
	http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">


	<bean id="HelloAOP1" class="com.example.demolearn.other.spring.demo4.HelloAOP1">
	</bean>

	<!-- 切面 -->
	<bean id="HelloAOP1_ASPECT" class="com.example.demolearn.other.spring.demo4.HelloAOP1_ASPECT"/>

	<!-- 切面规则 -->
	<aop:config>
		<aop:aspect id="aspect1" ref="HelloAOP1_ASPECT">
			<!-- 切点 -->
			<aop:pointcut id="pointcut1"
						  expression="execution(* com.example.demolearn.other.spring.demo4.*.*(..))"/>

			<aop:before pointcut-ref="pointcut1" method="beforeAdvice"/>

			<aop:after pointcut-ref="pointcut1" method="afterAdvice"/>

			<aop:after-returning pointcut-ref="pointcut1"
								 returning="retVal"
								 method="afterReturningAdvice"/>

			<aop:after-throwing pointcut-ref="pointcut1"
								throwing="ex"
								method="AfterThrowingAdvice"/>
		</aop:aspect>
	</aop:config>


</beans>

public class HelloAOP1 {
	private Integer age;

	public void setAge(Integer age){
		this.age = age;
	}

	public Integer getAge(){
		System.out.println("Age : " + age);
		return age;
	}

	public void printThrowException(){
		throw new IllegalArgumentException();
	}
}


//切面
public class HelloAOP1_ASPECT {
	public void beforeAdvice(){
		System.out.println("beforeAdvice");
	}

	public void afterAdvice(){
		System.out.println("afterAdvice");
	}

	public void afterReturningAdvice(Object retVal){
		System.out.println("afterReturningAdvice:" + retVal);
	}

	public void AfterThrowingAdvice(IllegalArgumentException ex){
		System.out.println("AfterThrowingAdvice");
	}
}



public class HelloAOP1_TEST {
	public static void main(String[] args){

		ApplicationContext context = new ClassPathXmlApplicationContext("./other/AOP.xml");
		HelloAOP1 HelloAOP1 =(HelloAOP1)context.getBean("HelloAOP1");
		HelloAOP1.setAge(111);
		System.out.println("----------------");
		HelloAOP1.getAge();
		// System.out.println("----------------");
		// HelloAOP1.printThrowException();
	}
}

输出1

在这里插入图片描述

在这里插入图片描述

输出2

在这里插入图片描述

在这里插入图片描述

5.2、基于Aspect来实现—>方法规则式拦截

<?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"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
	http://www.springframework.org/schema/aop
	http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">

	<!--开启aspectj注解-->
	<aop:aspectj-autoproxy/>
	<bean id="HelloAOP2" class="com.example.demolearn.other.spring.demo4.HelloAOP2">
	</bean>

	<bean id="HelloAOP2_ASPECT" class="com.example.demolearn.other.spring.demo4.HelloAOP2_ASPECT">
	</bean>

</beans>

public class HelloAOP2 {
	private Integer age;

	public void setAge(Integer age){
		this.age = age;
	}

	public Integer getAge(){
		System.out.println("Age : " + age);
		return age;
	}

	public void printThrowException(){
		throw new IllegalArgumentException();
	}
}

//切面
@Aspect
public class HelloAOP2_ASPECT {

	@Pointcut("execution(* com.example.demolearn.other.spring.demo4.*.*(..))")
	private void pointcut1(){
	}

	@Before("pointcut1()")
	public void beforeAdvice(){
		System.out.println("beforeAdvice");
	}

	@After("pointcut1()")
	public void afterAdvice(){
		System.out.println("afterAdvice");
	}

	@AfterReturning(pointcut = "pointcut1()", returning = "retVal")
	public void afterReturningAdvice(Object retVal){
		System.out.println("afterReturningAdvice:" + retVal);
	}

	@AfterThrowing(pointcut = "pointcut1()", throwing = "ex")
	public void AfterThrowingAdvice(IllegalArgumentException ex){
		System.out.println("AfterThrowingAdvice");
	}
}

public class HelloAOP2_TEST {
	public static void main(String[] args){

		ApplicationContext context = new ClassPathXmlApplicationContext("./other/AOP2.xml");
		HelloAOP2 HelloAOP2 =(HelloAOP2)context.getBean("HelloAOP2");
		HelloAOP2.setAge(111);
		System.out.println("----------------");
		HelloAOP2.getAge();
		// System.out.println("----------------");
		// HelloAOP1.printThrowException();
	}
}
输出
-----

beforeAdvice
afterReturningAdvice:null
afterAdvice
----------------
beforeAdvice
Age : 111
afterReturningAdvice:111
afterAdvice

在这里插入图片描述

在这里插入图片描述

5.3、基于Aspect来实现—>方法注解式拦截

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


@Component
public class HelloAOP3 {
	private Integer age = 111;

	@HelloAOP3_annotation(name = "注解式拦截")
	public Integer getAge(){
		System.out.println("Age : " + age);
		return age;
	}

}


@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface HelloAOP3_annotation {
	String name();
}


//切面
@Aspect
@Component//自动注入
public class HelloAOP3_ASPECT {

	//注解切点
	@Pointcut("@annotation(com.example.demolearn.other.spring.demo4.autotationAop.HelloAOP3_annotation)")
	private void pointcut1(){
	}

	@Before("pointcut1()")
	public void beforeAdvice(){
		System.out.println("beforeAdvice");
	}

	@After("pointcut1()")
	public void afterAdvice(JoinPoint joinPoint){

		MethodSignature signature =(MethodSignature)joinPoint.getSignature();
		Method method = signature.getMethod();
		HelloAOP3_annotation helloAOP3_annotation = method.getAnnotation(HelloAOP3_annotation.class);
		System.out.println("注解式拦截 " + helloAOP3_annotation.name()); //5

		System.out.println("afterAdvice");
	}

	@AfterReturning(pointcut = "pointcut1()", returning = "retVal")
	public void afterReturningAdvice(Object retVal){
		System.out.println("afterReturningAdvice:" + retVal);
	}

	@AfterThrowing(pointcut = "pointcut1()", throwing = "ex")
	public void AfterThrowingAdvice(IllegalArgumentException ex){
		System.out.println("AfterThrowingAdvice");
	}
}



@Configuration
@ComponentScan("com.example.demolearn.other.spring.demo4.autotationAop")//扫描范围
@EnableAspectJAutoProxy //1 开启对AOP的支持
public class HelloAOP3_config {

}

public class HelloAOP3_TEST {
	public static void main(String[] args){

		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(HelloAOP3_config.class); // 1

		HelloAOP3 helloAOP3 =(HelloAOP3)context.getBean("helloAOP3");

		System.out.println("----------------");
		helloAOP3.getAge();

		context.close();
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值