AOP 面向切面编程,允许在 java 应用中的方法调用的前后做一些处理。

本文通过实例介绍两种主要的Spring AOP 配置方式:xml 方式配置,注解方式配置

XML 方式配置

1. 项目包类结构

2. App.java 启动类 代码

  1. package wqz.spring.aop;
  2.  
  3. import org.springframework.context.ApplicationContext;
  4. import org.springframework.context.support.ClassPathXmlApplicationContext;
  5.  
  6. public class App
  7. {
  8. public static void main( String[] args )
  9. {
  10. ApplicationContext appContext = new ClassPathXmlApplicationContext(
  11. new String[]{"SpringAOP.xml"});
  12. CustomerService cust = (CustomerService)appContext.getBean("customerServiceProxy");
  13. System.out.println("*************************");
  14. cust.printName();
  15. System.out.println("*************************");
  16. cust.printUrl();
  17. System.out.println("*************************");
  18. try {
  19. cust.printThrowException();
  20. } catch (Exception e) {
  21. }
  22. }
  23. }

 3. CustomerService.java 待切的类

  1. package wqz.spring.aop;
  2.  
  3. public class CustomerService {
  4. private String name;
  5. private String url;
  6.  
  7. public String getName() {
  8. return name;
  9. }
  10. public void setName(String name) {
  11. this.name = name;
  12. }
  13. public String getUrl() {
  14. return url;
  15. }
  16. public void setUrl(String url) {
  17. this.url = url;
  18. }
  19.  
  20. public void printName(){
  21. System.out.println("Customer name:"+this.name);
  22. }
  23.  
  24. public void printUrl(){
  25. System.out.println("Customer url:"+this.url);
  26. }
  27.  
  28. public void printThrowException() {
  29. throw new IllegalArgumentException();
  30. }
  31. }

 4. 切面处理类,有四种方式(Before,After,Around,Exception,自行百度)

  1. package wqz.spring.aop;
  2.  
  3. import java.lang.reflect.Method;
  4. import org.springframework.aop.AfterReturningAdvice;
  5.  
  6. public class HijackAfterMethod implements AfterReturningAdvice {
  7.  
  8. public void afterReturning(Object arg0, Method arg1, Object[] arg2,
  9. Object arg3) throws Throwable {
  10. System.out.println("After method hijack");
  11. }
  12. }
  1. package wqz.spring.aop;
  2.  
  3. import java.util.Arrays;
  4. import org.aopalliance.intercept.MethodInterceptor;
  5. import org.aopalliance.intercept.MethodInvocation;
  6.  
  7. public class HijackAroundMethod implements MethodInterceptor {
  8.  
  9. public Object invoke(MethodInvocation methodInvocation) throws Throwable {
  10. System.out.println("Method name : "
  11. + methodInvocation.getMethod().getName());
  12. System.out.println("Method arguments : "
  13. + Arrays.toString(methodInvocation.getArguments()));
  14.  
  15. // 相当于 MethodBeforeAdvice
  16. System.out.println("HijackAroundMethod : Before method hijacked!");
  17.  
  18. try {
  19. // 调用原方法,即调用CustomerService中的方法
  20. Object result = methodInvocation.proceed();
  21.  
  22. // 相当于 AfterReturningAdvice
  23. System.out.println("HijackAroundMethod : After method hijacked!");
  24.  
  25. return result;
  26.  
  27. } catch (IllegalArgumentException e) {
  28. // 相当于 ThrowsAdvice
  29. System.out.println("HijackAroundMethod : Throw exception hijacked!");
  30. throw e;
  31. }
  32. }
  33. }
  1. package wqz.spring.aop;
  2.  
  3. import java.lang.reflect.Method;
  4. import org.springframework.aop.MethodBeforeAdvice;
  5.  
  6. public class HijackBeforeMethod implements MethodBeforeAdvice{
  7.  
  8. public void before(Method arg0, Object[] arg1, Object arg2)
  9. throws Throwable {
  10. System.out.println("HijackBeforeMethod : Before method hijacked!");
  11. }
  12. }
  1. package wqz.spring.aop;
  2.  
  3. import org.springframework.aop.ThrowsAdvice;
  4.  
  5. public class HijackThrowException implements ThrowsAdvice {
  6. public void afterThrowing(IllegalArgumentException e) throws Throwable {
  7. System.out.println("HijackThrowException : Throw exception hijacked!");
  8. }
  9. }

5. Spring-Aop.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans
  5. http://www.springframework.org/schema/beans/spring-beans.xsd">
  6.  
  7. <!-- 被 监 督 对 象 创 建 -->
  8. <bean id="customerService" class="wqz.spring.aop.CustomerService">
  9. <property name="name" value="zoey"/>
  10. <property name="url" value="http://shiyanlou.com"/>
  11. </bean>
  12.  
  13. <!-- Advices 4种 类 型 的 通 知 对应的类分别如下-->
  14. <bean id="hijackBeforeMethodBean" class="wqz.spring.aop.HijackBeforeMethod"/>
  15. <bean id="hijackAfterMethodBean" class="wqz.spring.aop.HijackAfterMethod"/>
  16. <bean id="hijackThrowExceptionBean" class="wqz.spring.aop.HijackThrowException"/>
  17. <bean id="hijackAroundMethodBean" class="wqz.spring.aop.HijackAroundMethod" />
  18.  
  19. <!-- PointCut 根据名字或者正则 劫持 method -->
  20. <!-- 字符串匹配 创建 劫持bean -->
  21. <bean id="customerPointcut"
  22. class="org.springframework.aop.support.NameMatchMethodPointcut">
  23. <!-- 定义劫持方法名 -->
  24. <property name="mappedName" value="printName" />
  25. </bean>
  26.  
  27. <!-- 字符串匹配创建一个默认的Pointcut Advisor bean 用于 给 pointcut 配置 advice劫持 对象-->
  28. <bean id="customerAdvisor"
  29. class="org.springframework.aop.support.DefaultPointcutAdvisor">
  30. <!-- 将 定义的 customerPointcut 劫持到的方法 交由 advice处理 -->
  31. <property name="pointcut" ref="customerPointcut" />
  32.  
  33. <property name="advice" ref="hijackAroundMethodBean" />
  34. </bean>
  35.  
  36. <!-- 正则表达式 创建劫持bean
  37. <bean id="customerAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
  38. <property name="patterns">
  39. <list>
  40. <value>.*URL.*</value>
  41. </list>
  42. </property>
  43. <property name="advice" ref="hijackAroundMethodBean" />
  44. </bean>
  45. -->
  46.  
  47. <!-- 创 建 代 理 对 象 -->
  48. <bean id="customerServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
  49. <!-- 你 想 要 劫 持 的 对 象 -->
  50. <property name="target" ref="customerService"/>
  51. <!-- 你想使用 哪个对象 劫持 target -->
  52. <property name="interceptorNames">
  53. <list>
  54. <value>customerAdvisor</value>
  55. </list>
  56. </property>
  57. </bean>
  58. </beans>

6. 运行结果

  1. 十月 24, 2018 12:30:41 上午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
  2. 信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@ef98ce0: startup date [Wed Oct 24 00:30:41 CST 2018]; root of context hierarchy
  3. 十月 24, 2018 12:30:41 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
  4. 信息: Loading XML bean definitions from class path resource [SpringAOP.xml]
  5. 十月 24, 2018 12:30:41 上午 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
  6. 信息: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@6b308ce5: defining beans [customerService,hijackBeforeMethodBean,hijackAfterMethodBean,hijackThrowExceptionBean,hijackAroundMethodBean,customerPointcut,customerAdvisor,customerServiceProxy]; root of factory hierarchy
  7. *************************
  8. Method name : printName
  9. Method arguments : []
  10. HijackAroundMethod : Before method hijacked!
  11. Customer name:zoey
  12. HijackAroundMethod : After method hijacked!
  13. *************************
  14. Customer url:http://shiyanlou.com
  15. *************************

注解方式

1. 包结构

2. 相关类代码

  1. package wqz.app;
  2.  
  3. import org.springframework.context.support.ClassPathXmlApplicationContext;
  4. import wqz.service.UserServiceInterface;
  5.  
  6. public class App {
  7. public static void main(String[] args) {
  8. ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("root-context.xml");
  9. UserServiceInterface interface1 = context.getBean(UserServiceInterface.class);
  10. interface1.sayHello();
  11. context.close();
  12. }
  13. }
  1. package wqz.service;
  2.  
  3. import org.springframework.stereotype.Service;
  4.  
  5. @Service
  6. public class UserService implements UserServiceInterface{
  7. public UserService() {
  8. // TODO Auto-generated constructor stub
  9. System.out.println(this.getClass().getSimpleName() + " constructor!!!!");
  10. }
  11. public void sayHello(){
  12. try {
  13. Thread.sleep(1000);
  14. } catch (InterruptedException e) {
  15. // TODO Auto-generated catch block
  16. e.printStackTrace();
  17. }
  18. System.out.println("========== Hello =========");
  19. }
  20. }
  1. package wqz.service;
  2.  
  3. public interface UserServiceInterface {
  4. public void sayHello();
  5. }
  1. package wqz.spring.aop.annotion;
  2.  
  3. import org.aspectj.lang.ProceedingJoinPoint;
  4. import org.aspectj.lang.annotation.Around;
  5. import org.aspectj.lang.annotation.Aspect;
  6. import org.springframework.stereotype.Service;
  7.  
  8. @Service
  9. @Aspect
  10. public class TimeMonitor {
  11. @Around("execution(* wqz.service.UserService.sayHello())")
  12. public void monitorAround(ProceedingJoinPoint pjp)throws Throwable{
  13. System.out.println("method start time: " + System.currentTimeMillis());
  14. Object re = pjp.proceed();
  15. System.out.println("method end time: " + System.currentTimeMillis());
  16. }
  17. }

3. 运行结果

  1. 十月 24, 2018 12:56:00 上午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
  2. 信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@a8e13ab: startup date [Wed Oct 24 00:56:00 CST 2018]; root of context hierarchy
  3. 十月 24, 2018 12:56:00 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
  4. 信息: Loading XML bean definitions from class path resource [root-context.xml]
  5. 十月 24, 2018 12:56:01 上午 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
  6. 信息: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@4be6d4a8: defining beans [org.springframework.aop.config.internalAutoProxyCreator,userService,timeMonitor,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor]; root of factory hierarchy
  7. UserService constructor!!!!
  8. method start time: 1540313761817
  9. ========== Hello =========
  10. method end time:
  11. 十月 24, 2018 12:56:02 上午 org.springframework.context.support.ClassPathXmlApplicationContext doClose
  12. 信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@a8e13ab: startup date [Wed Oct 24 00:56:00 CST 2018]; root of context hierarchy
  13. 十月 24, 2018 12:56:02 上午 org.springframework.beans.factory.support.DefaultListableBeanFactory destroySingletons
  14. 信息: Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@4be6d4a8: defining beans [org.springframework.aop.config.internalAutoProxyCreator,userService,timeMonitor,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor]; root of factory hierarchy

注解解析:

TimeMonitir 类 的注解 :

@Service和@Aspect,第一个注解是使得TimeMonitor受Spring托管并实例化。@Aspect就是使得这个类具有AOP功能(你可以这样理解)两个注解缺一不可;

@Around表示包围一个函数,也就是可以在函数执行前做一些事情,也可以在函数执行后做一些事情

"execution(* wqz.service.UserService.sayHello())"使用表达式的方式指定了要对哪个函数进行包围

补充:

@Around("within(@org.springframework.stereotype.Service wqz.spring.*)")

,意思是匹配wqz.spring包下所有使用@Service注解的类;

以下文档来自Spring中文开发指南2.5文档,由满江红开源组织翻译:

 
Spring AOP 用户可能会经常使用 execution切入点指示符。执行表达式的格式如下:
  1. executionmodifiers-pattern? ret-type-pattern declaring-type-pattern? name-patternparam-pattern
  2. throws-pattern?)
除了返回类型模式(上面代码片断中的ret-type-pattern),名字模式和参数模式以外, 所有的部分都是可选的。返回类型模式决定了方法的返回类型必须依次匹配一个连接点。 你会使用的最频繁的返回类型模式是*,它代表了匹配任意的返回类型。 一个全限定的类型名将只会匹配返回给定类型的方法。名字模式匹配的是方法名。 你可以使用*通配符作为所有或者部分命名模式。 参数模式稍微有点复杂:()匹配了一个不接受任何参数的方法, 而(..)匹配了一个接受任意数量参数的方法(零或者更多)。 模式(*)匹配了一个接受一个任何类型的参数的方法。 模式(*,String)匹配了一个接受两个参数的方法,第一个可以是任意类型, 第二个则必须是String类型。更多的信息请参阅AspectJ编程指南中语言语义的部分。
下面给出一些通用切入点表达式的例子。
  • 任意公共方法的执行:
    1. executionpublic * *(..))
  • 任何一个名字以“set”开始的方法的执行:
    1. execution(* set*(..))
  • AccountService接口定义的任意方法的执行:
    1. execution(* com.xyz.service.AccountService.*(..))
  • 在service包中定义的任意方法的执行:
    1. execution(* com.xyz.service.*.*(..))
  • 在service包或其子包中定义的任意方法的执行:
    1. execution(* com.xyz.service..*.*(..))
  • 在service包中的任意连接点(在Spring AOP中只是方法执行):
    1. withincom.xyz.service.*)
  • 在service包或其子包中的任意连接点(在Spring AOP中只是方法执行):
    1. withincom.xyz.service..*)
  • 实现了AccountService接口的代理对象的任意连接点 (在Spring AOP中只是方法执行):
    1. thiscom.xyz.service.AccountService
    'this'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得代理对象在通知体内可用。
  • 实现AccountService接口的目标对象的任意连接点 (在Spring AOP中只是方法执行):
    1. targetcom.xyz.service.AccountService
    'target'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得目标对象在通知体内可用。
  • 任何一个只接受一个参数,并且运行时所传入的参数是Serializable 接口的连接点(在Spring AOP中只是方法执行)
    1. argsjava.io.Serializable
    'args'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得方法参数在通知体内可用。
    请注意在例子中给出的切入点不同于 execution(* *(java.io.Serializable)): args版本只有在动态运行时候传入参数是Serializable时才匹配,而execution版本在方法签名中声明只有一个 Serializable类型的参数时候匹配。
  • 目标对象中有一个 @Transactional 注解的任意连接点 (在Spring AOP中只是方法执行)
    1. @targetorg.springframework.transaction.annotation.Transactional
    '@target'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得注解对象在通知体内可用。
  • 任何一个目标对象声明的类型有一个 @Transactional 注解的连接点 (在Spring AOP中只是方法执行):
    1. @withinorg.springframework.transaction.annotation.Transactional
    '@within'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得注解对象在通知体内可用。
  • 任何一个执行的方法有一个 @Transactional 注解的连接点 (在Spring AOP中只是方法执行)
    1. @annotationorg.springframework.transaction.annotation.Transactional
    '@annotation'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得注解对象在通知体内可用。
  • 任何一个只接受一个参数,并且运行时所传入的参数类型具有@Classified 注解的连接点(在Spring AOP中只是方法执行)
    1. @argscom.xyz.security.Classified
    '@args'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得注解对象在通知体内可用。
  • 任何一个在名为'tradeService'的Spring bean之上的连接点 (在Spring AOP中只是方法执行):
    1. beantradeService
  • 任何一个在名字匹配通配符表达式'*Service'的Spring bean之上的连接点 (在Spring AOP中只是方法执行):
    1. bean(*Service

****************************************************************

========= over ===========

Spring AOP配置方式的更多相关文章

  1. Spring AOP配置简单记录(注解及xml配置方式)

    在了解spring aop中的关键字(如:连接点(JoinPoint).切入点(PointCut).切面(Aspact).织入(Weaving).通知(Advice).目标(Target)等)后进行了 ...

  2. spring aop注解方式与xml方式配置

    注解方式 applicationContext.xml 加入下面配置 <!--Spring Aop 启用自动代理注解 --> <aop:aspectj-autoproxy proxy ...

  3. perf4j+spring+aop 配置 注解方式

    今天将perf4j基于spring aop方式进入了接入,接入方法还是比较简单.具体配置如下: logback.xml <!--perf4j配置--> <appender name= ...

  4. (转)Spring AOP实现方式(转)

    我们可以通过三种方式来使用Spring AOP,它们分别是:@Aspect-based(Annotation),Schema-based(XML),以及底层的Spring AOP API 底层的Spr ...

  5. Java--简单的Spring AOP配置以及AOP事物管理,JDK/GCLib动态代理

    一.看一下简单的通过XML的AOP配置 1.首先创建一个简单的Student类 public class Student { private Integer age; private String n ...

  6. spring aop配置文档部分翻译

    欢迎转载交流: http://www.cnblogs.com/shizhongtao/p/3476973.html 下面的文字来自官方文档的翻译,具体事例以后奉上. Advisors "ad ...

  7. spring aop配置及用例说明(1)

    欢迎转载交流,博客地址http://www.cnblogs.com/shizhongtao/p/3469776.html 首先,什么是aop,其实通俗一点讲就是,再方法执行时候我们加入其它业务逻辑.比 ...

  8. Spring AOP实现方式四之注入式AspectJ切面【附源码】

    现在我们要讲的是第四种AOP实现之注入式AspectJ切面 通过简单的配置就可以实现AOP了. 源码结构: 1.首先我们新建一个接口,love 谈恋爱接口. package com.spring.ao ...

  9. Spring AOP实现方式三之自动扫描注入【附源码】

    注解AOP实现  这里唯一不同的就是application 里面 不需要配置每个bean都需要配置了,直接自动扫描 注册,主要知识点是怎么通过配置文件得到bean, 注意类前面的@注解. 源码结构: ...

随机推荐

  1. redis的缓冲击穿|缓冲雪崩|缓冲淘汰

    Redis 的缓存穿透和击穿 查询数据 缓存中有,从缓存中返回 缓存中没有,从数据库中查找,数据库中命中结果 ,将查询到的数据保存到缓存中 缓存中没有,从数据库中查找,数据库中也没有 , 不在缓存中保 ...

  2. linux redis 启动 overcommit_memory

    Redis在启动时不成功, 查看日志发现如下警告: WARNING overcommit_memory is set to 0! Background save may fail under low ...

  3. 一分钟搭建Spring Boot

    1.首先你的电脑需要安装jdk.Apache Maven.Intellij IDEA 2.新建项目  (敲重点,有的同学有没有Spring Initializr 这个请到本文章后面看安装步骤) 3.选 ...

  4. CSS 表单

    输入框前有图片 老板让你实现在输入框前有图片的功能.老板觉得用图片代替文字更有说服力. 要实现这样的功能很简单,它的原理是将图片放在内边距内. 代码 1 2 3 4 5 6 7 8 9 10 11 1 ...

  5. Secondary Indices

    [Secondary Indices] EOSIO has the ability to sort tables by up to 16 indices.  A table's struct cann ...

  6. Linux查看某个端口的连接数

    一.查看哪些IP连接本机 netstat -an 二.查看TCP连接数 1)统计80端口连接数 netstat -nat | grep -i "80" | wc -l 2)统计ht ...

  7. 解决yum安装ftp提示仓库 的 GPG 密钥已安装,但是不适用于此软件包。

    遇到的问题: 在linux系统使用yum install ftp安装ftp,报以下错误 warning: rpmts_HdrFromFdno: Header V3 RSA/SHA1 Signature ...

  8. spring boot 整合 elasticsearch 5.x

    spring boot与elasticsearch集成有两种方式.一种是直接使用elasticsearch.一种是使用data中间件. 本文只指针使用maven集成elasticsearch 5.x, ...

  9. 图像的几何变换——OpenCV-Python Tutorials

    原文地址http://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_geometric_tran ...

  10. ToolBar+Drawable实现一个好用的侧滑栏(侧边栏)和工具栏

    先参考下ToolBar的使用和DrawableLayout的使用: 1.主界面布局,主要结构包含一个ToolBar和一个DrawableLayout,DrawableLayout里面有左侧边栏布局和主 ...