基本概念
1.连接点 :可以增强的方法叫做连接点(现在的理解是自己创建的类都是链接点 以后学深入了在来修改)
2.切入点 : 实际被增强的方法
3.通知 :方法的增强部分叫做通知(具体通知在后面写)
4.切面:就是动作(不太懂过后补上)
通知类型
前置通知 @Before(value = “execution( *** )”)
环绕通知 @Around(value = “execution( *** )”)
异常通知 @AfterThrowing(value = “execution( *** )”)
返回通知 @AfterReturning(value = “execution( *** )”)
最终通知 @After(value = “execution(* execution( *** )”)
基于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"
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.xsd
">
<!--目标对象-->
<bean id="user" class="com.xzh.test.User"></bean>
<!--切面对象-->
<bean id="userAspectJ" class="com.xzh.test.UserAspectJ"></bean>
<!--配置织入:告诉spring框架 哪些方法(切点)需要进行哪些增强(前置、后置...)-->
<aop:config>
<!--声明切面-->
<aop:aspect ref="userAspectJ">
<!--抽取切点表达式-->
<aop:pointcut id="myPointcut" expression="execution(* com.xzh.test.User.add(..))"></aop:pointcut>
<!--切面:切点+通知-->
<!--<aop:before method="before" pointcut="execution(* com.xzh.test.User.add(..))"/>-->
<!--<aop:before method="before" pointcut="execution(* com.xzh.test.User.add(..))"/>
<aop:after-returning method="afterReturning" pointcut="execution(* com.xzh.test.User.add(..))"/>-->
<!--<aop:around method="around" pointcut="execution(* com.xzh.test.User.add(..))"/>
<aop:after-throwing method="afterThrowing" pointcut="execution(* com.xzh.test.User.add(..))"/>
<aop:after method="after" pointcut="execution(* com.xzh.test.User.add(..))"/>-->
<aop:around method="Around" pointcut-ref="myPointcut"/>
<aop:after method="After" pointcut-ref="myPointcut"/>
</aop:aspect>
</aop:config>
</beans>
基于配置类方法:
和之前的差别有 首先要在配置类上加上@EnableAspectJAutoProxy表示开启动态代理
增强类(动态代理类) 要加上@Aspect 声明他是一个增强类
其次每种通知 都要加上 value 配置增强的是哪个类或方法
1.首先创建Spring配置类
@Configuration
@ComponentScan(basePackages = {"com.xzh.test"})
@EnableAspectJAutoProxy
public class SpringConfig {
}
2.增强类的代码和被增强类:
package com.xzh.Spring5.AspectJ;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Repository;
/**
* @Author XuZhuHong
* @CreateTime 2021/5/19 10:35
* 主函数
*/
public class TestAop {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
User user = context.getBean("user", User.class);
user.add();
}
}
/**
* 重点****************************************************************************
* UserAspectJ类 (增强)
*/
@Component//创建对象
@Aspect//声明这是一个增强类(动态代理)
// 如果有多个增强类增强一个方法 用@Order(数字)注解来设置优先级 数字越小越先执行
class UserAspectJ {
//这是用Pointcut注解 把切入点提取出来方便复用
// * 代表所有权限 后面的 com.**** 代表要增强的方法 add里面的 .. 表示参数列表
@Pointcut(value = "execution(* com.xzh.Spring5.AspectJ.User.add(..))")
public void Pointcut(){}
//也可以用定义常量的方式来填写
// final String execution="execution(* com.xzh.Spring5.AspectJ.User.add(..))";
//如果要增强多个方法:写法如下:
// @Pointcut(value = "execution(* com.xzh.test.User.add(..)) || execution(* com.xzh.test.User.delete(..))")
//通知执行的顺序如下
//每一个通知里面的value必须要有 现在这里面用的是调用配置的方法来填写value
//下面这一句就是说明 增加前置通知 格式必须这样写
@Before(value = "Pointcut()")
//等价于:@Before(value = "execution(* com.xzh.Spring5.AspectJ.User.add(..))")
public void Before() {
System.out.println("UserAspectJ before执行了");
}
//环绕通知 就是在方法前执行和方法后执行 在执行前后需要调用本体方法
//这个方法通知是有点特殊的 必须要传入一个参数 这个参数是用来执行本体方法的
@Around(value ="Pointcut()")
public void Around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("UserAspectJ Around前 执行了");
//调用proceed()来执行原来的方法
pjp.proceed();
System.out.println("UserAspectJ Around后 执行了");
}
//当程序有异常会执行的通知
@AfterThrowing(value ="Pointcut()")
public void AfterThrowing() {
System.out.println("UserAspectJ AfterThrowing 执行了");
}
//返回通知 如果AfterThrowing通知执行 这个则不会执行
@AfterReturning(value = "Pointcut()")
public void AfterReturning() {
System.out.println("UserAspectJ AfterReturning 执行了");
}
//最终通知 在本体方法执行后的执行方法 这个无论如何都会执行
@After(value = "Pointcut()")
public void After() {
System.out.println("UserAspectJ after执行了");
}
}
/************************************************************************************
* User类 (被增强)
*/
@Repository//创建对象的注解
class User {
public void add(){
System.out.println("User add 执行了");
}
}
运行结果