Spring AOP配置方式
2018-10-24 08:45:39来源:博客园 阅读 ()
AOP 面向切面编程,允许在 java 应用中的方法调用的前后做一些处理。
本文通过实例介绍两种主要的Spring AOP 配置方式:xml 方式配置,注解方式配置
XML 方式配置
1. 项目包类结构
2. App.java 启动类 代码
package wqz.spring.aop; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class App { public static void main( String[] args ) { ApplicationContext appContext = new ClassPathXmlApplicationContext( new String[]{"SpringAOP.xml"}); CustomerService cust = (CustomerService)appContext.getBean("customerServiceProxy"); System.out.println("*************************"); cust.printName(); System.out.println("*************************"); cust.printUrl(); System.out.println("*************************"); try { cust.printThrowException(); } catch (Exception e) { } } }
3. CustomerService.java 待切的类
package wqz.spring.aop; public class CustomerService { private String name; private String url; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public void printName(){ System.out.println("Customer name:"+this.name); } public void printUrl(){ System.out.println("Customer url:"+this.url); } public void printThrowException() { throw new IllegalArgumentException(); } }
4. 切面处理类,有四种方式(Before,After,Around,Exception,自行百度)
package wqz.spring.aop; import java.lang.reflect.Method; import org.springframework.aop.AfterReturningAdvice; public class HijackAfterMethod implements AfterReturningAdvice { public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable { System.out.println("After method hijack"); } }
package wqz.spring.aop; import java.util.Arrays; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; public class HijackAroundMethod implements MethodInterceptor { public Object invoke(MethodInvocation methodInvocation) throws Throwable { System.out.println("Method name : " + methodInvocation.getMethod().getName()); System.out.println("Method arguments : " + Arrays.toString(methodInvocation.getArguments())); // 相当于 MethodBeforeAdvice System.out.println("HijackAroundMethod : Before method hijacked!"); try { // 调用原方法,即调用CustomerService中的方法 Object result = methodInvocation.proceed(); // 相当于 AfterReturningAdvice System.out.println("HijackAroundMethod : After method hijacked!"); return result; } catch (IllegalArgumentException e) { // 相当于 ThrowsAdvice System.out.println("HijackAroundMethod : Throw exception hijacked!"); throw e; } } }
package wqz.spring.aop; import java.lang.reflect.Method; import org.springframework.aop.MethodBeforeAdvice; public class HijackBeforeMethod implements MethodBeforeAdvice{ public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable { System.out.println("HijackBeforeMethod : Before method hijacked!"); } }
package wqz.spring.aop; import org.springframework.aop.ThrowsAdvice; public class HijackThrowException implements ThrowsAdvice { public void afterThrowing(IllegalArgumentException e) throws Throwable { System.out.println("HijackThrowException : Throw exception hijacked!"); } }
5. Spring-Aop.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 被 监 督 对 象 创 建 --> <bean id="customerService" class="wqz.spring.aop.CustomerService"> <property name="name" value="zoey"/> <property name="url" value="http://shiyanlou.com"/> </bean> <!-- Advices 4种 类 型 的 通 知 对应的类分别如下--> <bean id="hijackBeforeMethodBean" class="wqz.spring.aop.HijackBeforeMethod"/> <bean id="hijackAfterMethodBean" class="wqz.spring.aop.HijackAfterMethod"/> <bean id="hijackThrowExceptionBean" class="wqz.spring.aop.HijackThrowException"/> <bean id="hijackAroundMethodBean" class="wqz.spring.aop.HijackAroundMethod" /> <!-- PointCut 根据名字或者正则 劫持 method --> <!-- 字符串匹配 创建 劫持bean --> <bean id="customerPointcut" class="org.springframework.aop.support.NameMatchMethodPointcut"> <!-- 定义劫持方法名 --> <property name="mappedName" value="printName" /> </bean> <!-- 字符串匹配创建一个默认的Pointcut Advisor bean 用于 给 pointcut 配置 advice劫持 对象--> <bean id="customerAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor"> <!-- 将 定义的 customerPointcut 劫持到的方法 交由 advice处理 --> <property name="pointcut" ref="customerPointcut" /> <property name="advice" ref="hijackAroundMethodBean" /> </bean> <!-- 正则表达式 创建劫持bean <bean id="customerAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> <property name="patterns"> <list> <value>.*URL.*</value> </list> </property> <property name="advice" ref="hijackAroundMethodBean" /> </bean> --> <!-- 创 建 代 理 对 象 --> <bean id="customerServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <!-- 你 想 要 劫 持 的 对 象 --> <property name="target" ref="customerService"/> <!-- 你想使用 哪个对象 劫持 target --> <property name="interceptorNames"> <list> <value>customerAdvisor</value> </list> </property> </bean> </beans>
6. 运行结果
十月 24, 2018 12:30:41 上午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh 信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@ef98ce0: startup date [Wed Oct 24 00:30:41 CST 2018]; root of context hierarchy 十月 24, 2018 12:30:41 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions 信息: Loading XML bean definitions from class path resource [SpringAOP.xml] 十月 24, 2018 12:30:41 上午 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons 信息: 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 ************************* Method name : printName Method arguments : [] HijackAroundMethod : Before method hijacked! Customer name:zoey HijackAroundMethod : After method hijacked! ************************* Customer url:http://shiyanlou.com *************************
注解方式
1. 包结构
2. 相关类代码
package wqz.app; import org.springframework.context.support.ClassPathXmlApplicationContext; import wqz.service.UserServiceInterface; public class App { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("root-context.xml"); UserServiceInterface interface1 = context.getBean(UserServiceInterface.class); interface1.sayHello(); context.close(); } }
package wqz.service; import org.springframework.stereotype.Service; @Service public class UserService implements UserServiceInterface{ public UserService() { // TODO Auto-generated constructor stub System.out.println(this.getClass().getSimpleName() + " constructor!!!!"); } public void sayHello(){ try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("========== Hello ========="); } }
package wqz.service; public interface UserServiceInterface { public void sayHello(); }
package wqz.spring.aop.annotion; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.springframework.stereotype.Service; @Service @Aspect public class TimeMonitor { @Around("execution(* wqz.service.UserService.sayHello())") public void monitorAround(ProceedingJoinPoint pjp)throws Throwable{ System.out.println("method start time: " + System.currentTimeMillis()); Object re = pjp.proceed(); System.out.println("method end time: " + System.currentTimeMillis()); } }
3. 运行结果
十月 24, 2018 12:56:00 上午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh 信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@a8e13ab: startup date [Wed Oct 24 00:56:00 CST 2018]; root of context hierarchy 十月 24, 2018 12:56:00 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions 信息: Loading XML bean definitions from class path resource [root-context.xml] 十月 24, 2018 12:56:01 上午 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons 信息: 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 UserService constructor!!!! method start time: 1540313761817 ========== Hello ========= method end time: 1540313762817 十月 24, 2018 12:56:02 上午 org.springframework.context.support.ClassPathXmlApplicationContext doClose 信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@a8e13ab: startup date [Wed Oct 24 00:56:00 CST 2018]; root of context hierarchy 十月 24, 2018 12:56:02 上午 org.springframework.beans.factory.support.DefaultListableBeanFactory destroySingletons 信息: 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文档,由满江红开源组织翻译:
execution
切入点指示符。执行表达式的格式如下:execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)
*
,它代表了匹配任意的返回类型。 一个全限定的类型名将只会匹配返回给定类型的方法。名字模式匹配的是方法名。 你可以使用*
通配符作为所有或者部分命名模式。 参数模式稍微有点复杂:()
匹配了一个不接受任何参数的方法, 而(..)
匹配了一个接受任意数量参数的方法(零或者更多)。 模式(*)
匹配了一个接受一个任何类型的参数的方法。 模式(*,String)
匹配了一个接受两个参数的方法,第一个可以是任意类型, 第二个则必须是String类型。更多的信息请参阅AspectJ编程指南中 语言语义的部分。-
任意公共方法的执行:
execution(public * *(..))
-
任何一个名字以“set”开始的方法的执行:
execution(* set*(..))
-
AccountService
接口定义的任意方法的执行:execution(* com.xyz.service.AccountService.*(..))
-
在service包中定义的任意方法的执行:
execution(* com.xyz.service.*.*(..))
-
在service包或其子包中定义的任意方法的执行:
execution(* com.xyz.service..*.*(..))
-
在service包中的任意连接点(在Spring AOP中只是方法执行):
within(com.xyz.service.*)
-
在service包或其子包中的任意连接点(在Spring AOP中只是方法执行):
within(com.xyz.service..*)
-
实现了
AccountService
接口的代理对象的任意连接点 (在Spring AOP中只是方法执行):this(com.xyz.service.AccountService)
'this'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得代理对象在通知体内可用。 -
实现
AccountService
接口的目标对象的任意连接点 (在Spring AOP中只是方法执行):target(com.xyz.service.AccountService)
'target'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得目标对象在通知体内可用。 -
任何一个只接受一个参数,并且运行时所传入的参数是
Serializable
接口的连接点(在Spring AOP中只是方法执行)args(java.io.Serializable)
'args'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得方法参数在通知体内可用。请注意在例子中给出的切入点不同于execution(* *(java.io.Serializable))
: args版本只有在动态运行时候传入参数是Serializable时才匹配,而execution版本在方法签名中声明只有一个Serializable
类型的参数时候匹配。 -
目标对象中有一个
@Transactional
注解的任意连接点 (在Spring AOP中只是方法执行)@target(org.springframework.transaction.annotation.Transactional)
'@target'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得注解对象在通知体内可用。 -
任何一个目标对象声明的类型有一个
@Transactional
注解的连接点 (在Spring AOP中只是方法执行):@within(org.springframework.transaction.annotation.Transactional)
'@within'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得注解对象在通知体内可用。 -
任何一个执行的方法有一个
@Transactional
注解的连接点 (在Spring AOP中只是方法执行)@annotation(org.springframework.transaction.annotation.Transactional)
'@annotation'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得注解对象在通知体内可用。 -
任何一个只接受一个参数,并且运行时所传入的参数类型具有
@Classified
注解的连接点(在Spring AOP中只是方法执行)@args(com.xyz.security.Classified)
'@args'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得注解对象在通知体内可用。 -
任何一个在名为'
tradeService
'的Spring bean之上的连接点 (在Spring AOP中只是方法执行):bean(tradeService)
-
任何一个在名字匹配通配符表达式'
*Service
'的Spring bean之上的连接点 (在Spring AOP中只是方法执行):bean(*Service)
****************************************************************
========= over ===========
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- Spring系列.ApplicationContext接口 2020-06-11
- springboot2配置JavaMelody与springMVC配置JavaMelody 2020-06-11
- 给你一份超详细 Spring Boot 知识清单 2020-06-11
- SpringBoot 2.3 整合最新版 ShardingJdbc + Druid + MyBatis 2020-06-11
- 掌握SpringBoot-2.3的容器探针:实战篇 2020-06-11
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash