一、基本概念

1.AOP简介

DI能够让相互协作的软件组件保持松散耦合;而面向切面编程(aspect-oriented programming,AOP)允许你把遍布应用各处的功能分离出来形成可重用的组件。把这些横切关注点与业务逻辑相分离正是面向切面编程(AOP)所要解决的问题

常见场景:日志、安全、事物、缓存

2.AOP用到的一些术语

项目中每个模块的核心功能都是为特定业务领域提供服务,但是这些模块都需要类似的辅助功能,例如安全和事务管理,这时候需要引入AOP的概念。

通知定义了切面是什么以及何时使用, Spring切面可以应用5种类型的通知:

  • 前置通知(Before):在目标方法被调用之前调用通知功能;
  • 后置通知(After):在目标方法完成之后调用通知,此时不会关心方法的输出是什么;
  • 返回通知(After-returning):在目标方法成功执行之后调用通知;
  • 异常通知(After-throwing):在目标方法抛出异常后调用通知;
  • 环绕通知(Around):通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为。

连接点(join potint)是在应用执行过程中能够插入切面的一个点。这个点可以是调用方法时、抛出异常时、甚至修改一个字段时。切面代码可以利用这些点插入到应用的正常流程之中,并添加新的行为

切点(poincut)的定义会匹配通知所要织入的一个或多个连接点。我们通常使用明确的类和方法名称,或是利用正则表达式定义所匹配的类和方法名称来指定这些切点

二、准备service模块

1.service bean

public class CategoryService1 {public void add(int id) {System.out.println("CategoryService1.add()");}
}public class CategoryService2{public void add(int id) {System.out.println("CategoryService2.add()");}
}

2.配置bean

<?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"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-4.2.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-4.2.xsd"><bean id="categoryServiceImpl" class="service.CategoryService1"></bean>
<bean id="CategoryServiceImpl2" class="service.CategoryService2"></bean>
</beans>

3.单元测试

@Test
public void test(){ApplicationContext context=new ClassPathXmlApplicationContext("aop.xml");CategoryService1 service1=context.getBean(CategoryService1.class);service1.add(1);CategoryService2 service2=context.getBean(CategoryService2.class);service2.add(2);
}

运行结果:

CategoryService1.add()

CategoryService2.add()

三、XML方式声明AOP

Spring所创建的通知都是用标准的Java类编写的, 定义通知所应用的切点通常会使用注解或在Spring配置文件里采用XML来编写,这两种语法对于Java开发者来说都是相当熟悉的。

注意Spring只支持方法级别的连接点。

切入点表达式

execution指示器是我们在编写切点定义时最主要使用的指示器

Demo

我们要实现的一个简单示例是:在service方法调用前和调用后打印日志“write log”。

public class LogHandler {public void log(){System.out.println("write log.");}
}

aop.xml添加配置:

<bean id="logHandler" class="pointcut.LogHandler"></bean><aop:config><aop:aspect id="log" ref="logHandler"><aop:pointcut id="addLog" expression="execution(* service.*.*(..))"></aop:pointcut><aop:before method="log" pointcut-ref="addLog"></aop:before><aop:after method="log" pointcut-ref="addLog"></aop:after></aop:aspect></aop:config> 

单元测试:

public class AopTests {@Testpublic void test() {ApplicationContext context = new ClassPathXmlApplicationContext("aop.xml");CategoryService1 service1 = context.getBean(CategoryService1.class);service1.add(1);CategoryService2 service2 = context.getBean(CategoryService2.class);service2.add(2);}
}

运行报错:

org.aspectj.weaver.reflect.ReflectionWorld$ReflectionWorldException

原来是忘了pom依赖:

<dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>${spring.version}</version>
</dependency> 

运行结果:

write log.

CategoryService1.add()

write log.

write log.

CategoryService2.add()

write log.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>DemoStore</groupId><artifactId>DemoAOP</artifactId><version>1.0-SNAPSHOT</version><properties><spring.version>4.3.5.RELEASE</spring.version></properties><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>RELEASE</version></dependency></dependencies></project>

完整的pom.xml

四、aop:around

通过使用环绕通知,可以实现前置通知和后置通知所实现的功能,而且只需要在一个方法中实现。

public class LogTimeHandler {public void log(ProceedingJoinPoint jp) throws Throwable {try {System.out.println("1.before log "+new Date().getTime());//记录开始时间jp.proceed();System.out.println("2.after log "+new Date().getTime());//记录结束时间}catch (Exception e){System.out.println("log fail ");}}
}

  

在aop1.xml中配置aop:round通知

<?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="categoryService" class="service.CategoryService1"></bean><bean id="logHanlder" class="pointcut.LogTimeHandler"></bean><aop:config><aop:aspect id="log" ref="logHanlder"><aop:pointcut id="addlog" expression="execution(* service.*.*(..))"></aop:pointcut><aop:around method="log" pointcut-ref="addlog"></aop:around></aop:aspect></aop:config>
</beans>

  

单元测试:

public class AopTest1 {@Testpublic void test(){ApplicationContext context=new ClassPathXmlApplicationContext("aop1.xml");CategoryService1 service1=context.getBean(CategoryService1.class);service1.add(1);}
}

运行结果:

1.before log 1489990832246
CategoryService1.add()
2.after log 1489990832263

  

五、注解方式创建AOP

定义切面需要给类添加@Aspect注解。然后需要给方法添加注解来声明通知方法,各通知类型对应的注解:

  • @After 通知方法会在目标方法返回或抛出异常后
  • @AfterReturning 通知方法会在目标方法返回后调用
  • @AfterThrowing 通知方法会在目标方法抛出异常后调用
  • @Around 通知方法会将目标方法封装起来
  • @Before 通知方法会在目标方法调用之前执行
@Component
@Aspect
public class LogHelper3 {@Before("execution(* service.*.*(..))")public void logStart(){System.out.println("log start "+new Date().getTime());}
}

然后定义JavaConfig类,注意需要给类添加@EnableAspectJAutoProxy注解启用自动代理功能。

@Configuration
@EnableAspectJAutoProxy
@ComponentScan(basePackageClasses = {service.CategoryService3.class,pointcut.LogHelper3.class})
public class BeanConfig {
}

  单元测试:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = BeanConfig.class)
public class AopTest3 {@AutowiredCategoryService3 service;@Testpublic void testConfigAop(){service.add(100);}
}

运行结果:

log start 1489990977264
add category id=100

  

结尾:

参考:《spring实战》

源码下载:https://github.com/cathychen00/learnjava/tree/master/DemoAOP

转载于:https://www.cnblogs.com/janes/p/6873732.html

JAVA入门[14]-Spring MVC AOP相关推荐

  1. Spring MVC AOP切面失效原因与处理

    Spring MVC AOP切面失效原因与处理 问题概述 AOP的两类实现 解决方案 方法一:用Autowired 注入自身的实例 方法二:从Spring上下文获取增强后的实例引用 方法三: 利用Ao ...

  2. java动态菜单显示实现,java – 为Spring MVC / AOP应用程序实现动态菜单

    我希望为我的 Spring MVC应用程序实现动态可更改的菜单(无论何时添加带注释的方法或控制器). 我想要的是引入新的注释(@RequestMenuMapping),它将转到@Controller ...

  3. 如何用Java类配置Spring MVC(不通过web.xml和XML方式)

    DispatcherServlet是Spring MVC的核心,按照传统方式, 需要把它配置到web.xml中. 我个人比较不喜欢XML配置方式, XML看起来太累, 冗长繁琐. 还好借助于Servl ...

  4. Java开发【Spring之AOP详解(xml--注解->方法增强、事务管理(声明事务的实现))】

    文章目录 引入 一.AOP概述 1.什么是AOP 2.AOP的优势及使用场景 3.AOP实现原理 二.代理模式 1.代理模式概念 2.代理模式分类 3.静态代理演示 定义HouseAgencyComp ...

  5. Java面试题--spring mvc

    什么是Spring MVC ?简单介绍下你对springMVC的理解? Spring MVC是一个基于MVC架构的用来简化web应用程序开发的应用开发框架,它是Spring的一个模块,无需中间整合层来 ...

  6. Java Web(11) Spring MVC 返回Json

    2019独角兽企业重金招聘Python工程师标准>>> 1. 首先是对Spring mvc 进行xml配置 <?xml version="1.0" enco ...

  7. java地址映射关系,Spring MVC——基础(简介,使用,地址映射)

    "大佬们"嘴中的SSH,SSM框架,我这种小白终于解除到第二个S了,关于Spring MVC框架,根据最近的学习发现,还是有很多不足和需要加强巩固的地方,所以,通过总结博客的方式将 ...

  8. [Java] Maven 建立 Spring MVC 工程

    GIT: https://github.com/yangyxd/Maven.SpringMVC.Web 1. 建立 WebApp 工程 下一步: 下一步: 选择 maven-archetype-web ...

  9. Java web学习——Spring MVC项目实例,三层架构通过JDBC链接SQLServer2012

    Spring MVC架构原理?原理篇 1.新建项目 File-New-Other,选择Dynamic web project 项目建好后的目录结构如下: 2.导入jar包 导入spring mvc框架 ...

  10. Java中级篇——Spring MVC 是什么(附加响应状态代码列举)

    1.关于springMVC 基于Spring框架,主要解决后端服务器接受客户端服务器接受客户提交的请求,并给予响应相关的问题.的框架 目录 1.关于springMVC 基于Spring框架,主要解决后 ...

最新文章

  1. 华为H3C ER3100由器限速方法合集
  2. LVS三种模式的区别及负载均衡算法
  3. 【转】Jenkins详细教程
  4. 课程目标IO java
  5. oracle ns,RAC到单实例SWITCHOVER
  6. AJAX,JSON与MVC
  7. 软件事务内存导论(五)创建嵌套事务
  8. java打字小游戏源码_java实现快速打字游戏
  9. vscode: Code Runner直接运行多文件C++程序
  10. PDA应用软件开发特点
  11. 视频工具箱android,小熊视频工具箱
  12. 基于双边滤波的人脸美化
  13. epoch ,steps_per_epoch and batchsize解读
  14. 今天开始学Java log2N的表示
  15. 嵌入式开发模拟红外测距仪---UDP通信实现无线装置
  16. 一些简单的js技术 实现点击 的js隐藏显示
  17. C语言基础指针知识点总结
  18. 第十八届全国大学智能汽车竞赛报名信息统计
  19. 怎么解决浏览器提示无法加载shockwave flash?
  20. C语言实现员工管理系统

热门文章

  1. 【转】Eclipse下支持编写HTML/JS/CSS/JSP页面的自动提示
  2. xtrabackup备份还原的具体操作过程
  3. 【Win 10应用开发】认识一下UAP项目
  4. delphi三层架构中注册服务器
  5. 如何不显示index.php,tp如何隐藏index.php
  6. 图片在mysql中的储存_如何在MySQL中直接储存图片
  7. python 排序统计滤波器_数字图像处理的python实现(8)——中值滤波
  8. Unity编辑器控件的使用(—)
  9. ParticleSystem的使用
  10. 使用@Validated分组遇到的坑及解决方案