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代理,前者基于接口,后者基于子类
如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级交流:854630135,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家。
二 Spring AOP
Spring中的AOP代理还是离不开Spring的IOC容器,代理的生成,管理及其依赖关系都是由IOC容器负责,Spring默认使用JDK动态代理,在需要代理类而不是代理接口的时候,Spring会自动切换为使用CGLIB代理,不过现在的项目都是面向接口编程,所以JDK动态代理相对来说用的还是多一些。
三 基于注解的AOP配置方式
1.启用@AsjectJ支持
在applicationContext.xml中配置下面一句:
2.通知类型介绍
(1)Before:在目标方法被调用之前做增强处理,@Before只需要指定切入点表达式即可
(2)AfterReturning:在目标方法正常完成后做增强,@AfterReturning除了指定切入点表达式后,还可以指定一个返回值形参名returning,代表目标方法的返回值
(3)AfterThrowing:主要用来处理程序中未处理的异常,@AfterThrowing除了指定切入点表达式后,还可以指定一个throwing的返回值形参名,可以通过该形参名
来访问目标方法中所抛出的异常对象
(4)After:在目标方法完成之后做增强,无论目标方法时候成功完成。@After可以指定一个切入点表达式
(5)Around:环绕通知,在目标方法完成前后做增强处理,环绕通知是最重要的通知类型,像事务,日志等都是环绕通知,注意编程中核心是一个ProceedingJoinPoint
3.例子:
spring框架 AOP核心详解
(1)Operator.java -- 切面类
@Componentbr/@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
(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通知的运行,不要同时使用!同时使用也没啥意义。
如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级交流:854630135,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家。
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的名称
后言: spring 的环绕通知和前置通知,后置通知有着很大的区别,主要有两个重要的区别:
1) 目标方法的调用由环绕通知决定,即你可以决定是否调用目标方法,而前置和后置通知 是不能决定的,他们只是在方法的调用前后执行通知而已,即目标方法肯定是要执行的。
2) 环绕通知可以控制返回对象,即你可以返回一个与目标对象完全不同的返回值,虽然这很危险,但是你却可以办到。而后置方法是无法办到的,因为他是在目标方法返回值后调用
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 {
@Resource
private LogService logService;
public Object record(ProceedingJoinPoint pjp){
Log log = new Log();
try {
log.setOperator(admin);
String mname = pjp.getSignature().getName();
log.setOperName(mname);
//方法参数,本例中是User user
Object[] args = pjp.getArgs();
log.setOperParams(Arrays.toString(args));
//执行目标方法,返回的是目标方法的返回值,本例中 void
Object 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
注意切入点表达式,!bean(logService) 做日志通知的时候,不要给日志本身做日志,否则会造成无限循环!
如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级交流:854630135,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家。
有关更详细的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,记住这个就行了。
spring框架 AOP核心详解的更多相关文章
- Spring框架学习-Spring的AOP概念详解
一.SpringAOP的概述. AOP(Aspect Oriented Programming),面向切面编程,通过预编译方式和运行期间动态代理实现程序的功能的统一维护的技术.AOP是OOP(面向对象 ...
- Spring框架系列(6) - Spring IOC实现原理详解之IOC体系结构设计
在对IoC有了初步的认知后,我们开始对IOC的实现原理进行深入理解.本文将帮助你站在设计者的角度去看IOC最顶层的结构设计.@pdai Spring框架系列(6) - Spring IOC实现原理详解 ...
- Spring框架系列(7) - Spring IOC实现原理详解之IOC初始化流程
上文,我们看了IOC设计要点和设计结构:紧接着这篇,我们可以看下源码的实现了:Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的. ...
- Spring框架系列(8) - Spring IOC实现原理详解之Bean实例化(生命周期,循环依赖等)
上文,我们看了IOC设计要点和设计结构:以及Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的:容器中存放的是Bean的定义即Be ...
- Spring框架的核心功能之AOP技术
技术分析之Spring框架的核心功能之AOP技术 AOP的概述 1. 什么是AOP的技术? * 在软件业,AOP为Aspect Oriented Programming的 ...
- Spring各个jar包详解
Spring各jar包详解 spring.jar 是包含有完整发布模块的单个jar 包.但是不包括mock.jar,aspects.jar, spring-portlet.jar, and sprin ...
- Spring Batch(4): Job详解
Spring Batch(4): Job详解 2016-03-26 18:46 870人阅读 评论(1) 收藏 举报 分类: Spring(6) 版权声明:本文为博主原创文章,未经博主允许不得转载 ...
- 跟着刚哥学习Spring框架--AOP(五)
AOP AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善.OOP引入 ...
- RPC框架调用过程详解
RPC框架调用过程详解 2017年09月16日 21:14:08 荷叶清泉 阅读数 6275 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. ...
随机推荐
- CentOS 4.8/OEL4.8 配置本地yum
下载createrepo包并安装 下载地址: ftp://195.220.108.108/linux/dag/redhat/el4/en/i386/dag/RPMS/createrepo-0.4.6- ...
- 最新版Postman的下载及安装
1. 操作环境 Windows Windows 7旗舰版 64位 , Windows 10专业版 Postman Postman-win64-5.1.3-Setup.exe 2. Postman的资 ...
- 【Selenium专题】元素定位之CssSelector
CssSelector是我最喜欢的元素定位方法,Selenium官网的Document里极力推荐使用CSS locator,而不是XPath来定位元素,原因是CSS locator比XPath loc ...
- axure rp 8.0注册码(亲测)
今天在看一需求原型时,发现其他部门发过来是8.0版的,老的7不能用,找了个亲测可用的验证码. License:米 业成 (STUDENT)Key:nFmqBBvEqdvbiUjy8NZiyWiRSg3 ...
- k8s API sample
Declarative API k8s: cluster-api Introduction to Kubernetes Cluster-API Project Declarative Manageme ...
- 20165310 NetSec2019 Week6 Exp4 恶意代码分析
20165310 NetSec2019 Week6 Exp4 恶意代码分析 一.实验要求 1.系统运行监控 使用如计划任务,每隔一分钟记录自己的电脑有哪些程序在联网,连接的外部IP是哪里.运行一段时间 ...
- Received empty response from Zabbix Agent at [172.16.1.7]...
Centos7.5 zabbix添加主机发现ZBX爆红报错 原因:在配置/etc/zabbix/zabbix_agentd.conf中172.16.1.71写成了127.16.1.71 解决方法:重 ...
- freeswitch控制台日志级别设置以及存储
1.在管理控制台上设置 console loglevel (0~7)越往上级别越大 2.打开sip详细日志 sofia profile internal siptrace on 3.关闭sip详细日志 ...
- P4782 【模板】2-SAT 问题
https://www.luogu.org/problemnew/show/P4782 链接 https://www.luogu.org/problemnew/show/P4782 思路 选a就必须选 ...
- SpringBoot 使用Mybatis-Plus
简介 Mybatis-Plus(简称MP)是一个 Mybatis 的增强工具,在 Mybatis 的基础上只做增强不做改变,为简化开发.提高效率而生. 特性 无侵入:Mybatis-Plus 在 My ...