Spring AOP配置方式
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:
- 十月 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 ===========
Spring AOP配置方式的更多相关文章
- Spring AOP配置简单记录(注解及xml配置方式)
在了解spring aop中的关键字(如:连接点(JoinPoint).切入点(PointCut).切面(Aspact).织入(Weaving).通知(Advice).目标(Target)等)后进行了 ...
- spring aop注解方式与xml方式配置
注解方式 applicationContext.xml 加入下面配置 <!--Spring Aop 启用自动代理注解 --> <aop:aspectj-autoproxy proxy ...
- perf4j+spring+aop 配置 注解方式
今天将perf4j基于spring aop方式进入了接入,接入方法还是比较简单.具体配置如下: logback.xml <!--perf4j配置--> <appender name= ...
- (转)Spring AOP实现方式(转)
我们可以通过三种方式来使用Spring AOP,它们分别是:@Aspect-based(Annotation),Schema-based(XML),以及底层的Spring AOP API 底层的Spr ...
- Java--简单的Spring AOP配置以及AOP事物管理,JDK/GCLib动态代理
一.看一下简单的通过XML的AOP配置 1.首先创建一个简单的Student类 public class Student { private Integer age; private String n ...
- spring aop配置文档部分翻译
欢迎转载交流: http://www.cnblogs.com/shizhongtao/p/3476973.html 下面的文字来自官方文档的翻译,具体事例以后奉上. Advisors "ad ...
- spring aop配置及用例说明(1)
欢迎转载交流,博客地址http://www.cnblogs.com/shizhongtao/p/3469776.html 首先,什么是aop,其实通俗一点讲就是,再方法执行时候我们加入其它业务逻辑.比 ...
- Spring AOP实现方式四之注入式AspectJ切面【附源码】
现在我们要讲的是第四种AOP实现之注入式AspectJ切面 通过简单的配置就可以实现AOP了. 源码结构: 1.首先我们新建一个接口,love 谈恋爱接口. package com.spring.ao ...
- Spring AOP实现方式三之自动扫描注入【附源码】
注解AOP实现 这里唯一不同的就是application 里面 不需要配置每个bean都需要配置了,直接自动扫描 注册,主要知识点是怎么通过配置文件得到bean, 注意类前面的@注解. 源码结构: ...
随机推荐
- redis的缓冲击穿|缓冲雪崩|缓冲淘汰
Redis 的缓存穿透和击穿 查询数据 缓存中有,从缓存中返回 缓存中没有,从数据库中查找,数据库中命中结果 ,将查询到的数据保存到缓存中 缓存中没有,从数据库中查找,数据库中也没有 , 不在缓存中保 ...
- linux redis 启动 overcommit_memory
Redis在启动时不成功, 查看日志发现如下警告: WARNING overcommit_memory is set to 0! Background save may fail under low ...
- 一分钟搭建Spring Boot
1.首先你的电脑需要安装jdk.Apache Maven.Intellij IDEA 2.新建项目 (敲重点,有的同学有没有Spring Initializr 这个请到本文章后面看安装步骤) 3.选 ...
- CSS 表单
输入框前有图片 老板让你实现在输入框前有图片的功能.老板觉得用图片代替文字更有说服力. 要实现这样的功能很简单,它的原理是将图片放在内边距内. 代码 1 2 3 4 5 6 7 8 9 10 11 1 ...
- Secondary Indices
[Secondary Indices] EOSIO has the ability to sort tables by up to 16 indices. A table's struct cann ...
- Linux查看某个端口的连接数
一.查看哪些IP连接本机 netstat -an 二.查看TCP连接数 1)统计80端口连接数 netstat -nat | grep -i "80" | wc -l 2)统计ht ...
- 解决yum安装ftp提示仓库 的 GPG 密钥已安装,但是不适用于此软件包。
遇到的问题: 在linux系统使用yum install ftp安装ftp,报以下错误 warning: rpmts_HdrFromFdno: Header V3 RSA/SHA1 Signature ...
- spring boot 整合 elasticsearch 5.x
spring boot与elasticsearch集成有两种方式.一种是直接使用elasticsearch.一种是使用data中间件. 本文只指针使用maven集成elasticsearch 5.x, ...
- 图像的几何变换——OpenCV-Python Tutorials
原文地址http://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_geometric_tran ...
- ToolBar+Drawable实现一个好用的侧滑栏(侧边栏)和工具栏
先参考下ToolBar的使用和DrawableLayout的使用: 1.主界面布局,主要结构包含一个ToolBar和一个DrawableLayout,DrawableLayout里面有左侧边栏布局和主 ...