目录
创建Spring的配置文件,引入具体的AOP的schema约束:
AOP 面向切面编程,底层是jdk动态代理实现的。
为什么要引入aop面向切面编程?
可以在不修改源代码的前提下,对程序进行增强!!
切入点表达式:
详细解析: pointcut="execution(public void com.qcby.demo1.UserServiceImpl.save())"
execution() 格式规范 语法结构
public void com.qcby.demo1.UserServiceImpl.save() 要增强的方法们
public 可写可不写 4个权限修饰符 私有的Private 公共的public 默认的default 同包下的protected
void 返回值 必须写 可以编写为* 但不能省略不写的
com.qcby.demo1.UserServiceImpl 包名+类名 不能省略不写的,编写为 *
*.*ServiceImpl 表示:任何包下的任何以ServiceImpl结尾的类都符合增强要求
save() 方法名称 可以写 * 或 *save();
参数列表 save后括号里面的内容 (..) 表示任意类型和个数的参数
比较通用的表达式:execution(public * com.qcby.*.*ServiceImpl.*(..))
AOP的通知类型有:
1. 前置通知 目标方法执行前,进行增强。
2. 最终通知 目标方法执行成功或者失败,进行增强。
3. 后置通知 目标方法执行成功后,进行增强。
4. 异常通知 目标方法执行失败后,进行增强。
5. 环绕通知 目标方法执行前后,都可以进行增强。目标对象的方法需要手动执行。
AOP入门程序实例:(配置文件方式)
创建maven项目,导入其特定坐标依赖
<!-- AOP联盟 -->
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<!-- Spring Aspects -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<!-- aspectj -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.3</version>
</dependency>
创建Spring的配置文件,引入具体的AOP的schema约束:
<?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
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
</beans>
创建业务层接口+实现类,并将业务层实现类加到配置文件中:
public interface UserService {
public void save();
}
/**
* 用户业务层实现类
*/
public class UserServiceImpl implements UserService {
//保存方法
// @Override
public void save() {
System.out.println("业务层方法执行了!!!");
//int i=5/0;
}
}
定义切面类,并将切面类加到配置文件中:
/**
* 定义自己的切面类
* 自定义切面类 = 切入点(表达式) + 通知(增强的代码)
*/
public class MyXmlAspect {
/**
* 通知
*/
public void log(){
// 发送手机短信
// 发送邮件/记录日志/事务管理
System.out.println("增强的方法执行了...");
}
/**
* 异常
*/
public void log01(){
// 发送手机短信
// 发送邮件/记录日志/事务管理
System.out.println("增强的方法的异常执行了...");
}
/**
* 最终
*/
public void log02(){
// 发送手机短信
// 发送邮件/记录日志/事务管理
System.out.println("增强的方法的最终执行了...");
}
/**
* 环绕通知
*/
public void logAround(ProceedingJoinPoint point){
try {
System.out.println("前置增强的方法执行了...");
//执行业务逻辑
//目的执行目标对象的业务逻辑 jdk动态代理 methed.invok执行目标方法
// 让目标对象的方法去执行
point.proceed();
System.out.println("后置通知方法执行了!!!");
}catch (Throwable e){
e.printStackTrace();
//出现异常执行的
System.out.println("异常通知方法执行了!!!");
}finally {
//无论如何都要执行的
System.out.println("最终通知方法执行了!!!");
}
}
}
在配置文件中完成aop的配置,声明切面类:
<?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
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--将用户模块的实现类交给spring去管理-->
<bean id="userService" class="com.qcby.demo1.UserServiceImpl"/>
<!--将切面类交给spring去管理-->
<bean id="myXmlAspect" class="com.qcby.demo1.MyXmlAspect"/>
<!--
切入点表达式 解析 pointcut="execution(public void com.qcby.demo1.UserServiceImpl.save())"
execution() 格式规范 语法结构
public void com.qcby.demo1.UserServiceImpl.save() 要增强的方法们
public 可写可不写 4个 私有的 公共的 默认的 同包下的
void 返回值 必须写 可以编写 * 不能省略不写的
com.qcby.demo1.UserServiceImpl 包名+类名 不能省略不写的,编写 *
*.*ServiceImpl 任何包下的任何以ServiceImpl结尾的类都符合增强要求
save() 方法名称 可以写 * *save();
参数列表 (..) 表示任意类型和个数的参数
比较通用的表达式:execution(public * com.qcbyjy.*.*ServiceImpl.*(..))
-->
<!--配置AOP的增强-->
<aop:config>
<!--配置切面 = 切入点 + 通知组成-->
<aop:aspect ref="myXmlAspect">
<!--前置通知:UserServiceImpl的save方法执行前,会增强-->
<!--<aop:before method="log" pointcut="execution(public void com.qcby.demo1.UserServiceImpl.save())"/>-->
<!--最终-->
<!--<aop:after method="log02" pointcut="execution(public * com.qcby.*.*ServiceImpl.save(..))"/>-->
<!--后置-->
<!--<aop:after-returning method="log" pointcut="execution(public * com.qcby.*.*ServiceImpl.save(..))"/>-->
<!--异常-->
<!--<aop:after-throwing method="log01" pointcut="execution(public * com.qcby.*.*ServiceImpl.save(..))"/>-->
<!--环绕通知:目标方法执行前后,都可以进行增强。目标对象的方法需要手动执行。-->
<aop:around method="logAround" pointcut="execution(public * com.qcby.*.*ServiceImpl.save(..))"/>
</aop:aspect>
</aop:config>
</beans>
最终测试:
/**
* 测试类
* @RunWith(SpringJUnit4ClassRunner.class) 声明为测试单元
* @ContextConfiguration("classpath:applicationContext.xml") 加载配置文件
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class TestDemo1 {
@Autowired
private UserService userService;
@Test
public void run(){
userService.save();
}
}
运行结果: