一、相关概念
切入点表达式:指配置对哪个类的哪个方法进行增强的表达式。
格式:execution(表达式)
具体格式举例:
execution(public void com.yooyo.service.impl.AccountServiceImpl.findAll())
表示对修饰符为public返回值为void的com.yooyo.service.impl包下AccountServiceImpl类的无参方法findAll()进行增强
通配符格式举例:
execution(* com.yooyo.service.*.*ServiceImpl.findAll(…))
表示对任意返回值的com.yooyo.service.*包下的以ServiceImpl结尾的类的任意参数的findAll()
进行增强,其中修饰符省略 ,参数列表 …表示任何类型和个数
前置通知:在切入点方法之前执行
返回成功通知:在切入点方法执行成功之后执行
返回异常通知:在切入点方法抛出异常后执行
最终通知:不管切入点方法执行成功还是抛出异常都会执行
环绕通知:在切入点方法执行前后都可以执行,
需要在增强方法参数引入ProceedingJoinPoint,然后在增强方法中ProceedingJoinPoint.proceed()方法控制切入点方法的执行
二、具体实现
1.环境搭建
在已有环境及Demo上扩展,地址如下
2.创建切面类,并添加注解src/main/java/com.yooyo.aop/LogXmlAspect.java
@Component 将切面类交给容器管理
@Aspect 声明为切面类
@Around(value="")环绕通知
@Before(value="")前置通知
@AfterReturning(value="")返回成功通知
@AfterThrowing(value=" “)返回异常通知
@After(value=”")最终通知
@Pointcut("")定义切入点表达式
package com.yooyo.aop;
import org.aspectj.lang.ProceedingJoinPoint;
@Component
@Aspect
public class LogXmlAspect {
/**
* 最终通知测试
* @param jp
*/
@Around(value="pt()")
public void logAround(ProceedingJoinPoint jp) {
try {
System.out.println("环绕通知前置...");
Object proceed = jp.proceed();
System.out.println(proceed);
System.out.println("环绕通知返回成功...");
} catch (Throwable e) {
System.out.println("环绕通知抛出异常...");
e.printStackTrace();
}finally {
System.out.println("环绕通知最终...");
}
}
/**
* 其他通知测试
*/
/*@Before(value="execution(* com.yooyo.service.*.*ServiceImpl.findAll(..))")
@AfterReturning(value="execution(* com.yooyo.service.*.*ServiceImpl.findAll(..))")
@AfterThrowing(value="execution(* com.yooyo.service.*.*ServiceImpl.findAll(..))")
@After(value="execution(* com.yooyo.service.*.*ServiceImpl.findAll(..))")*/
public void log() {
System.out.println("aop输出日志...");
}
/**
*定义公共的切入点表达式
*/
@Pointcut("execution(* com.yooyo.service.*.*ServiceImpl.findAll(..))")
public void pt() {};
}
3.在spring配置文件,开启aop注解支持
aop:aspectj-autoproxy/:开启aop注解支持
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p" 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" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:component-scan base-package="com.yooyo">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
</context:component-scan>
<!-- 加载配置文件 -->
<context:property-placeholder location="classpath:config/jdbcConfig.properties" />
<!-- 配置数据源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}"></property>
<property name="jdbcUrl" value="${jdbc.url}"></property>
<property name="user" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!-- 配置MyBatis的Session工厂 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 数据库连接池 -->
<property name="dataSource" ref="dataSource" />
<!-- 加载mybatis的全局配置文件 -->
<property name="configLocation" value="classpath:mybatis/SqlMapConfig.xml" />
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.yooyo.dao" />
</bean>
<!-- 开启AOP注解支持 参数proxy-target-class="true" 强制使用cglib代理方式 -->
<aop:aspectj-autoproxy/>
</beans>