Spring AOP详细介绍
AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待,Struts2的拦截器设计就是基于AOP的思想,是个比较经典的例子。
一 AOP的基本概念
(1)Aspect(切面):通常是一个类,里面可以定义切入点和通知
(2)JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用
(3)Advice(通知):AOP在特定的切入点上执行的增强处理,有before,after,afterReturning,afterThrowing,around
(4)Pointcut(切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式
(5)AOP代理:AOP框架创建的对象,代理就是目标对象的加强。Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类
二 Spring AOP
Spring中的AOP代理还是离不开Spring的IOC容器,代理的生成,管理及其依赖关系都是由IOC容器负责,Spring默认使用JDK动态代理,在需要代理类而不是代理接口的时候,Spring会自动切换为使用CGLIB代理,不过现在的项目都是面向接口编程,所以JDK动态代理相对来说用的还是多一些。
三 基于注解的AOP配置方式
1.启用@AsjectJ支持
在applicationContext.xml中配置下面一句:
<aop:aspectj-autoproxy />
2.通知类型介绍
(1)Before:在目标方法被调用之前做增强处理,@Before只需要指定切入点表达式即可
(2)AfterReturning:在目标方法正常完成后做增强,@AfterReturning除了指定切入点表达式后,还可以指定一个返回值形参名returning,代表目标方法的返回值
(3)AfterThrowing:主要用来处理程序中未处理的异常,@AfterThrowing除了指定切入点表达式后,还可以指定一个throwing的返回值形参名,可以通过该形参名
来访问目标方法中所抛出的异常对象
(4)After:在目标方法完成之后做增强,无论目标方法时候成功完成。@After可以指定一个切入点表达式
(5)Around:环绕通知,在目标方法完成前后做增强处理,环绕通知是最重要的通知类型,像事务,日志等都是环绕通知,注意编程中核心是一个ProceedingJoinPoint
3.例子:
(1)Operator.java --> 切面类
@Component @Aspect public class Operator {@Pointcut("execution(* com.aijava.springcode.service..*.*(..))")public void pointCut(){}@Before("pointCut()")public void doBefore(JoinPoint joinPoint){System.out.println("AOP Before Advice...");}@After("pointCut()")public void doAfter(JoinPoint joinPoint){System.out.println("AOP After Advice...");}@AfterReturning(pointcut="pointCut()",returning="returnVal")public void afterReturn(JoinPoint joinPoint,Object returnVal){System.out.println("AOP AfterReturning Advice:" + returnVal);}@AfterThrowing(pointcut="pointCut()",throwing="error")public void afterThrowing(JoinPoint joinPoint,Throwable error){System.out.println("AOP AfterThrowing Advice..." + error);System.out.println("AfterThrowing...");}@Around("pointCut()")public void around(ProceedingJoinPoint pjp){System.out.println("AOP Aronud before...");try {pjp.proceed();} catch (Throwable e) {e.printStackTrace();}System.out.println("AOP Aronud after...");}}
(2)UserService.java --> 定义一些目标方法
@Service public class UserService {public void add(){System.out.println("UserService add()");}public boolean delete(){System.out.println("UserService delete()");return true;}public void edit(){System.out.println("UserService edit()");int i = 5/0;}}
(3).applicationContext.xml
<context:component-scan base-package="com.aijava.springcode"/><aop:aspectj-autoproxy />
(4).Test.java
public class Test {public static void main(String[] args) {ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");UserService userService = (UserService) ctx.getBean("userService");userService.add();} }
上面是一个比较简单的测试,基本涵盖了各种增强定义。注意:做环绕通知的时候,调用ProceedingJoinPoint的proceed()方法才会执行目标方法。
4.通知执行的优先级
进入目标方法时,先织入Around,再织入Before,退出目标方法时,先织入Around,再织入AfterReturning,最后才织入After。
注意:Spring AOP的环绕通知会影响到AfterThrowing通知的运行,不要同时使用!同时使用也没啥意义。
5.切入点的定义和表达式
切入点表达式的定义算是整个AOP中的核心,有一套自己的规范
Spring AOP支持的切入点指示符:
(1)execution:用来匹配执行方法的连接点
A:@Pointcut("execution(* com.aijava.springcode.service..*.*(..))")
第一个*表示匹配任意的方法返回值,..(两个点)表示零个或多个,上面的第一个..表示service包及其子包,第二个*表示所有类,第三个*表示所有方法,第二个..表示
方法的任意参数个数
B:@Pointcut("within(com.aijava.springcode.service.*)")
within限定匹配方法的连接点,上面的就是表示匹配service包下的任意连接点
C:@Pointcut("this(com.aijava.springcode.service.UserService)")
this用来限定AOP代理必须是指定类型的实例,如上,指定了一个特定的实例,就是UserService
D:@Pointcut("bean(userService)")
bean也是非常常用的,bean可以指定IOC容器中的bean的名称
6.基于XML形式的配置方式
开发中如果选用XML配置方式,通常就是POJO+XML来开发AOP,大同小异,无非就是在XML文件中写切入点表达式和通知类型
例子:
(1)Log.java
public class Log {private Integer id;//操作名称,方法名private String operName;//操作人private String operator;//操作参数private String operParams;//操作结果 成功/失败private String operResult;//结果消息private String resultMsg;//操作时间private Date operTime = new Date();setter,getter}
(2).Logger.java
/*** 日志记录器 (AOP日志通知)*/ public class Logger {@Resourceprivate LogService logService;public Object record(ProceedingJoinPoint pjp){Log log = new Log();try {log.setOperator("admin");String mname = pjp.getSignature().getName();log.setOperName(mname);//方法参数,本例中是User userObject[] args = pjp.getArgs();log.setOperParams(Arrays.toString(args));//执行目标方法,返回的是目标方法的返回值,本例中 voidObject obj = pjp.proceed();if(obj != null){log.setResultMsg(obj.toString());}else{log.setResultMsg(null);}log.setOperResult("success");log.setOperTime(new Date());return obj;} catch (Throwable e) {log.setOperResult("failure");log.setResultMsg(e.getMessage());} finally{logService.saveLog(log);}return null;} }
(3).applicationContext.xml
<aop:config><aop:aspect id="loggerAspect" ref="logger"><aop:around method="record" pointcut="(execution(* com.aijava.distributed.ssh.service..*.add*(..))or execution(* com.aijava.distributed.ssh.service..*.update*(..))or execution(* com.aijava.distributed.ssh.service..*.delete*(..)))and !bean(logService)"/></aop:aspect> </aop:config>
注意切入点表达式,!bean(logService) 做日志通知的时候,不要给日志本身做日志,否则会造成无限循环!
有关更详细的Spring AOP知识,可以查看Spring官方文档第9章Aspect Oriented Programming with Spring
7.JDK动态代理介绍
例子:
(1)UserService.java
public interface UserService {public void add(); }
(2)UserServiceImpl.java
public class UserServiceImpl implements UserService{public void add() {System.out.println("User add()...");}}
(3)ProxyUtils.java
public class ProxyUtils implements InvocationHandler{private Object target;public ProxyUtils(Object target){this.target = target;}public Object getTarget() {return target;}public void setTarget(Object target) {this.target = target;}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("do sth before...");method.invoke(target, args);System.out.println("do sth after...");return null;}}
(4)Test.java
public class Test {public static void main(String[] args) {UserService userService = new UserServiceImpl();ProxyUtils proxyUtils = new ProxyUtils(userService);UserService proxyObject = (UserService) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),UserServiceImpl.class.getInterfaces(), proxyUtils);proxyObject.add();} }
JDK动态代理核心还是一个InvocationHandler,记住这个就行了。
from: http://www.cnblogs.com/liuruowang/p/5711563.html
Spring AOP详细介绍相关推荐
- java项目功能详情介绍,JAVAEE—spring的详细介绍
一.spring介绍 1.三层架构中spring位置 2.spring一站式框架 正是因为spring框架性质是属于容器性质的. 容器中装什么对象就有什么功能.所以可以一站式. 不仅不排斥其他框架,还 ...
- Spring容器详细介绍
Spring容器 文章目录 一.Spring容器是什么,有什么作用? 二.如何让给Spring传递信息 1xml 2.java代码 3.注解 @component @controller @Servi ...
- spring AOP 之一:spring AOP功能介绍
https://www.cnblogs.com/duanxz/p/6754606.html
- AspectJ和Spring AOP(java动态代理和CGLIB)简单介绍
1.AOP介绍 什么是AOP:AOP就是面向切面编程.使用的背景: 1)我们的振隆维护着一千个方法,一天老板让振隆把这一千个方法都要加上事务代码(统一代码) 2)振隆咬咬牙,添加了一个新的方法,然后让 ...
- Spring入门篇——第6章 Spring AOP的API介绍
第6章 Spring AOP的API介绍 主要介绍Spring AOP中常用的API. 6-1 Spring AOP API的Pointcut.advice概念及应用 映射方法是sa开头的所有方法 如 ...
- Spring Cloud的核心成员、以及架构实现详细介绍
微服务架构系列 高并发架构系列:服务注册与发现的实现原理.及实现优劣势比较 阿里P8架构师谈:Restful.SOAP.RPC.SOA.微服务之间的区别 阿里P8架构师谈:微服务技术架构.监控.Doc ...
- AOP和Spring AOP介绍
AOP和Spring AOP介绍 文章目录 AOP和Spring AOP介绍 一.AOP简介 二. 传统开发存在的弊端 三. AOP实现原理 四.Spring AOP 五.AOP相关术语 一.AOP简 ...
- 高并发架构系列:Spring Cloud的核心成员、以及架构实现详细介绍
高并发架构系列:Spring Cloud的核心成员.以及架构实现详细介绍 什么是微服务 微服务的概念源于Martin Fowler所写的一篇文章"Microservices". 微 ...
- Spring AOP之HelloWorld与概念介绍(xml版)
Spring AOP之HelloWorld与概念介绍 什么是AOP Spring AOP代码实现 Spring AOP 基本概念介绍 目标类 连接点 切入点 切面 切面类 通知 通知类别 织入 什么是 ...
最新文章
- 用过多款团队协作工具后,少数派为什么选择飞书
- pgadmin使用教程
- 《我也能做CTO之程序员职业规划》写作过程重播之二
- Linux内核模块简介
- linux知识记录20192022
- Linux系统函数read()/write()/pread()/pwrite()的区别
- 怎么给域账号映射服务器,如何给每个域用户映射网络驱动器?
- 图像标注,三倍加速:谷歌AI新方案,数据民工的福音 | Demo可玩耍
- mysql中log_mysql中log
- 《深入解析IPv6(第3版)》——10.5 失效网关检测
- 拓端tecdat|R语言实现有限混合模型建模分析
- D1、D系列分辨率是多少
- Java应届生为什么找工作那么难
- NVIDIA显卡深度学习算力表
- 云计算概念简述(讲解)
- quarters自动编译生成sof
- .NET 实现手机短信验证接口
- Java实例——Java方法
- git命令--切换分支
- 宏观调控绝不是微观控制
热门文章
- 大数据分析:财务报表公开数据
- 短视频风口创业不容易,您信吗?
- php的数据校验,php 数据类型校验函数的简单示例
- 布道微服务_04服务的注册与发现
- Spring-整合多个配置文件
- Spring-在IoC中装配Bean系列文章导读
- Linux Performance Monitoring with Vmstat and Iostat Commands
- android:descendantFocusability
- mysql my.ini utf8_修改了my.ini没有效果,MySql的字符集还是没有变成utf8——mysql中文乱码...
- linux 文件类型 管理,Linux的文件类型及用户管理