导入依赖
pxm.xml
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--spring容器的核心依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<!--spring跟junit测试集成 注意junit测试的版本号要求是 4.12之上 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<!--
添加aop的依赖支持
spring-aop 需要表达式需要包!!!
-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
</dependencies>
beans.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:context="http://www.springframework.org/schema/context"
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/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--
在springboot框架出现之前
主流模式 都是半xml 半注解的方式
自己写的类用注解
别人写的类用配置文件
-->
<!--
扫描咱们自己写的类呢
1.配置包扫描
包名之间可以用,号分割
可以扫描父包 但是建议你多写几层
2.在类上加上注解
四个注解作用都是一样的 下面那三个更加见名知意
@Component
@Service
@Repository
@Controller
-->
<context:component-scan base-package="com.itheima.dao,com.itheima.service,com.itheima.logger"></context:component-scan>
<!--配置上 spring支持aop增强-->
<!--开启aop注解增强 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
例子
增强日志
LoggerAspect.java
/**
* 写增强的逻辑的增强逻辑 切面类 通知类
* 抽取一些增强逻辑方法
*
*
*/
@Component
//注解含义就是向spring说明 我这个类是是个切面类
@Aspect
public class LoggerAspect {
/**
* 无论 @Before @After ......
* 注解有参数 表达式
* 表示你对那些类的那些方法感兴趣 切入点表达式
*
* execution(方法修饰符 返回值类型 包名.包名.包名.包名.类名.方法名(参数类型) )
* 方法修饰符号 省略不写了!
* 返回值类型 一般都是写 *
*
* 后面的包名省略* 多级省略用..
* 参数也一样 多级省略.. 参数没有*
*
*/
@Pointcut("execution( * com.itheima.service..*.*(..))")
public void xyz(){
//这个方法的名字 无所谓 叫啥都行
}
// //@Before("execution( * com.itheima.service..*.*(..))")
// @Before("xyz()")
// public void logBefore(){
// System.out.println("原本对象就要执行方法之前***************");
//
// }
// //@AfterReturning("execution( * com.itheima.service..*.*(..))")
// @AfterReturning("xyz()")
// public void logCommon(){
// System.out.println("原本对象的方法之后正常运行了 会执行了....");
//
// }
// //@After("execution( * com.itheima.service..*.*(..))")
// @After("xyz()")
// public void logFinal(){
// System.out.println("原本对象的方法执行最终**************");
//
// }
//
//
// //@AfterThrowing("execution( * com.itheima.service..*.*(..))")
// @AfterThrowing("xyz()")
// public void logException(){
// System.out.println("方法执行的时候出现异常了");
// }
//环绕通知(增强)
@Around("xyz()")
/**
* joinPoint 就是对原本对象的方法封装
*/
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
Object result=null;
System.out.println("环绕通知前....");
try {
//有原本的方法吗?
Object[] args = joinPoint.getArgs();
System.out.println("获取原本对象的执行那一刻传递的参数!!!"+ Arrays.toString(args));
Class<? extends ProceedingJoinPoint> pointClass = joinPoint.getClass();
System.out.println("原本对象的类:"+pointClass);
Signature signature = joinPoint.getSignature();
System.out.println("原本对象的方法签名:"+signature);
//注意事项!!!!
//1.既然搞不清原本方法是否有返回值 那么 默认都有!!!
result = joinPoint.proceed();
System.out.println("环绕正常运行....");
}catch (Throwable e){
System.out.println("环绕发生异常....");
//注意事项!!!!
//万一原本的方法执行了 但是有异常?
//一种 真的do no thing 基本不会这么玩
//二种 抛出去!!!
throw e;
}finally {
System.out.println("环绕通知最终都会执行....");
}
return result;
}
}