赞
踩
Aop(面向切面编程):
它是一种编程思想,通过Aop将核心业务代码和其他代码(日志、事务等)分离出来,使得代码低耦合,高可用,提高了开发的效率
使用场景:日志记录,性能统计,安全控制,事务处理,异常处理等等
百度百科Aop:
Aop实现方案:
【重点讲解第三种方案的实现方式】
一:AspectJ强大的表达式:
表达式模板:execution(修饰符 返回值 包.类.方法名(参数) throws异常)
修饰符,一般省略
public 公共方法
* 任意
返回值,不能省略
void 返回没有值
String 返回值字符串
* 任意
包
com.zby.service 固定包
com.zby.oa.*.service oa包下面子包 (例如:com.zby.oa.flow.service)
com.zby.oa.. oa包下面的所有子包(含自己)
com.zby.oa.*.service.. oa包下面任意子包,固定目录service,service目录任意包
类
UserServiceImpl 指定类
*Impl 以Impl结尾
User* 以User开头
* 任意
方法名,不能省略
addUser 固定方法
add* 以add开头
*Do 以Do结尾
* 任意
(参数)
() 无参
(int) 一个整型
(int ,int) 两个
(..) 参数任意
throws ,可省略,一般不写
二:AspectJ支持5种类型的通知注解
before:前置通知
在方法执行前执行
afterReturning:后置通知
方法正常返回后执行,如果方法中抛出异常,通知无法执行,必须在方法执行后才执行,所以可以获得方法的返回值。
afterThrowing:抛出异常通知
方法抛出异常后执行,如果方法没有抛出异常,无法执行
after:最终通知
方法执行完毕后执行,无论方法中是否出现异常
around:环绕通知(很强大,可以直接代替其他四个通知)
方法执行前后分别执行,可以阻止方法的执行,必须手动执行目标方法
三:项目导入maven依赖
- <!-- Spring -->
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-context</artifactId>
- <version>4.3.12.RELEASE</version>
- </dependency>
- <!-- AspectJ -->
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-aspects</artifactId>
- <version>4.3.12.RELEASE</version>
- </dependency>
- <!-- 单元测试 -->
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>4.12</version>
- <scope>test</scope>
- </dependency>
四:基于xml配置实现AspectJ
1:定义UserController
- public class UserController {
- public int addUser() {
- return 1;
- }
- public int deleteUser() {
- return 1;
- }
- public int updateUser() {
- return 1;
- }
- }
2:定义切面类 实现功能:保存用户操作记录
- import org.aspectj.lang.JoinPoint;
- import org.aspectj.lang.ProceedingJoinPoint;
-
- public class AopLogging {
-
- // 前置通知
- public void before(JoinPoint joinPoint) {
- // 获取方法名称
- String name = joinPoint.getSignature().getName();
- // 获取方法参数
- Object[] args = joinPoint.getArgs();
-
- // 实际项目中根据session中的用户信息,保存操作记录到数据库
- if (name.equals("add")) {
- System.out.println("【用户执行添加操作】");
- } else if (name.equals("update")) {
- System.out.println("【用户执行更新操作】");
- } else {
- System.out.println("【用户执行删除操作】");
- }
- }
-
- // 返回通知 result:方法执行返回的结果
- public void afterReturning(JoinPoint joinPoint, Object result) {
- // 获取方法名称
- String name = joinPoint.getSignature().getName();
- // 打印方法执行结果
- System.out.println(name + "运行结果:" + result);
-
- }
-
- // 异常通知 exception:方法运行出错时抛出的异常
- public void afterThrowing(JoinPoint joinPoint, Exception exception) {
- // 获取方法名称
- String name = joinPoint.getSignature().getName();
- // 打印异常信息
- System.out.println(name + "运行异常信息:" + exception);
- }
-
- // 最终通知
- public void after(JoinPoint joinPoint) {
- System.out.println("最终通知");
- }
-
- //环绕通知
- public Object around(ProceedingJoinPoint joinPoint){
-
- //这里操作相当于前置通知
- System.out.println("环绕==前置通知");
-
- Object obj = null;
- try {
- obj = joinPoint.proceed();
- //这里操作是后置通知
- System.out.println("环绕==后置通知");
- } catch (Throwable e) {
- //这里操作是异常通知
- System.out.println("环绕==异常通知");
- e.printStackTrace();
- }
- System.out.println("环绕==最终通知");
- return obj;
- }
-
- }
3:配置xml
- <!-- 配置Bean -->
- <bean id="userController" class="com.mote.controller.UserController" />
-
- <bean id="aopLogging" class="com.mote.aop.AopLogging" />
-
- <aop:config>
- <!-- 配置切入点 -->
- <aop:pointcut id="pointcut"
- expression="execution(public * com.mote.controller.UserController.*(..)) " />
- <!-- 配置切面 -->
- <aop:aspect ref="aopLogging">
- <!-- 配置相应通知 -->
- <aop:before pointcut-ref="pointcut" method="before" />
- <!-- result和exception需要和方法中的参数一致 -->
- <aop:after-returning pointcut-ref="pointcut" method="afterReturning" returning="result" />
- <aop:after-throwing pointcut-ref="pointcut" method="afterThrowing" throwing="exception" />
- <aop:after pointcut-ref="pointcut" method="after" />
- <aop:around pointcut-ref="pointcut" method="around"/>
- </aop:aspect>
- </aop:config>
4:测试打印
- @Test
- public void testXml() {
- //创建容器
- ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
-
- //从容器中获取bean
- UserController userController = context.getBean(UserController.class);
-
- //调用方法
- userController.deleteUser();
-
- }
五:纯注解方式实现AspectJ
1:定义UserController,同上
2:定义切面类
- import org.aspectj.lang.JoinPoint;
- import org.aspectj.lang.ProceedingJoinPoint;
- import org.aspectj.lang.annotation.After;
- import org.aspectj.lang.annotation.AfterReturning;
- import org.aspectj.lang.annotation.AfterThrowing;
- import org.aspectj.lang.annotation.Around;
- import org.aspectj.lang.annotation.Aspect;
- import org.aspectj.lang.annotation.Before;
- import org.aspectj.lang.annotation.Pointcut;
-
- @Aspect //标注这是一个切面类
- public class AopLogging {
-
- //配置公共切点
- @Pointcut("execution(public * com.mote.controller.UserController.*(..))")
- public void pointcut(){}
-
- @Before("pointcut()")
- public void before(JoinPoint joinPoint) {
- // 获取方法名称
- String name = joinPoint.getSignature().getName();
- // 获取方法参数
- Object[] args = joinPoint.getArgs();
-
- // 实际项目中根据session中的用户信息,保存操作记录到数据库
- if (name.equals("add")) {
- System.out.println("【用户执行添加操作】");
- } else if (name.equals("update")) {
- System.out.println("【用户执行更新操作】");
- } else {
- System.out.println("【用户执行删除操作】");
- }
- }
-
- @AfterReturning(pointcut="pointcut()",returning="result")
- public void afterReturning(JoinPoint joinPoint, Object result) {
- // 获取方法名称
- String name = joinPoint.getSignature().getName();
- // 打印方法执行结果
- System.out.println(name + "运行结果:" + result);
-
- }
-
- @AfterThrowing(pointcut="pointcut()",throwing="exception")
- public void afterThrowing(JoinPoint joinPoint, Exception exception) {
- // 获取方法名称
- String name = joinPoint.getSignature().getName();
- // 打印异常信息
- System.out.println(name + "运行异常信息:" + exception);
- }
-
- @After("pointcut()")
- public void after(JoinPoint joinPoint) {
- System.out.println("最终通知");
- }
-
- @Around("pointcut()")
- public Object around(ProceedingJoinPoint joinPoint){
-
- //这里操作相当于前置通知
- System.out.println("环绕==前置通知");
-
- Object obj = null;
- try {
- obj = joinPoint.proceed();
- //这里操作相当于后置通知
- System.out.println("环绕==后置通知");
- } catch (Throwable e) {
- //这里操作相当于异常通知
- System.out.println("环绕==异常通知");
- e.printStackTrace();
- }
- //这里操作相当于最终通知
- System.out.println("环绕==最终通知");
- return obj;
- }
-
- }
3:注解配置类
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.context.annotation.EnableAspectJAutoProxy;
-
- import com.mote.aop.AopLogging;
- import com.mote.controller.UserController;
-
- @EnableAspectJAutoProxy //开启Spring支持AspectJ注解
- @Configuration
- public class MainConfig {
-
- @Bean //将UserController添加到spring容器
- public UserController userController(){
- return new UserController();
- }
-
- @Bean //将切面添加到容器
- public AopLogging aopLogging(){
- return new AopLogging();
- }
- }
或者使用xml
- <!-- 开启Spring支持AspectJ注解 -->
- <aop:aspectj-autoproxy/>
- <!-- 配置Bean -->
- <bean id="userController" class="com.mote.controller.UserController" />
- <bean id="aopLogging" class="com.mote.aop.AopLogging" />
4:测试打印
1:注解配置类对应的测试方法
- @Test
- public void test() {
- // 创建容器
- AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
-
- // 从容器中获取bean
- UserController userController = context.getBean(UserController.class);
-
- // 调用方法
- userController.deleteUser();
- }
2:xml配置对应的测试类
- @Test
- public void testXml() {
- // 创建容器
- ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
- "beans.xml");
-
- // 从容器中获取bean
- UserController userController = context.getBean(UserController.class);
-
- // 调用方法
- userController.deleteUser();
-
- }
注意一:JoinPoint joinPoint在方法的参数列表中,必须放在第一位,否则会报错
注意二:@AfterReturning和@AfterThrowing必须配置对应的returning和throwing参数
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。