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,记住这个就行了。
转载于:https://juejin.im/post/5c8b6a626fb9a049e6612377
spring框架 AOP核心详解相关推荐
- Spring框架面试题详解
1. 什么是spring? Spring 是个java企业级应用的开源开发框架.Spring主要用来开发Java应用,但是有些扩展是针对构建J2EE平台的web应用.Spring 框架目标是简化Jav ...
- 【Spring框架】全集详解
文章目录 ClassPathXmlApplicationContext工作原理 01.IOC:控制反转 02.什么是bean 03.DI注入以及c.p命名空间 ```p命名空间.c命名空间``` `` ...
- Spring之AOP原理详解
概念 AOP 实现原理 AOP 动态代理的实现原理 实现AOP 链接上一篇:spring框架组件分析 概念 AOP spring用代理类包裹切面,把他们织入到Spring管理的bean中.也就是说代理 ...
- Spring框架@PostConstruct注解详解
文章目录 前言 业务背景 通过依赖查找实现 `@PostConstruct`注解实现 @PostConstruct注解原理 `@PostConstruct`注解 `@PostConstruct`注解源 ...
- java spring框架 注解_详解Java的Spring框架中的注解的用法
1. 使用Spring注解来注入属性 1.1. 使用注解以前我们是怎样注入属性的类的实现: class UserManagerImpl implements UserManager { private ...
- Spring面向切面编程(AOP)详解
Spring面向切面编程(AOP)详解 面向切面编程(AOP)是Spring框架的另外一个重要的核心内容. 而在讲AOP之前,先来了解一下动态代理这个概念,因为AOP基于动态代理. 动态代理概念:在程 ...
- Spring 框架(Spring Framework)使用详解
概述 Spring 体系概述 Spring 是于2003年兴起的一个 full-stack 轻量级的 Java 开源框架,由 Rod Johnson 创建,使用 Spring 可以更快.更轻松.更安全 ...
- Spring包含JAR的详解
一.Spring 常用包的说明 spring.jar : 包含有完整发布模块的单个jar 包.但是不包括mock.jar, aspects.jar, spring-portlet.jar, and ...
- SpringBoot2.1.5(16)--- Spring Boot的日志详解
SpringBoot2.1.5(16)--- Spring Boot的日志详解 市面上有许多的日志框架,比如 JUL( java.util.logging), JCL( Apache Commons ...
最新文章
- R语言中的聚类的使用
- WinForm中Partial部分类的使用
- 牛客网 对称平方数【回文数的判断 两个vector是否相等】
- 如何在Android Wear上节省电池寿命
- Python核心教程(第二版)读书笔记(三)
- 猜数字游戏(Java)
- xshell修改编辑文件并保存
- 求给定数组中两数和为给定值的数量
- zk临时节点失效时间_dubbo学习(六)服务发布dubbo服务在zk的创建、订阅
- 新浪php工程师面试题
- 《心灵捕手》经典台词
- mysql数据库储存过程
- 医疗在线质控系统 资料收集
- 深入浅出的马尔科夫入门文章
- 杨振宁与清华计算机系,我们都误会杨振宁了!看到清华给出的工资,才明白他有多伟大...
- 日历当前月 日期对应
- 获取现在的Unix时间戳(Unix timestamp)的方法-在线时间戳转换器
- 如何在日内趋势中交易?
- 扔物线Kotlin讲解学习(一)----Kotlin的权限修饰符详解
- 老杨说运维 | 企业数字化转型中,统一监控的必要性
热门文章
- c++ builder xe2 (Embarcadero rad studio) 远程调试 同样适用于 delphi 远程调试 教程
- 如何在ashx页面获取Session值
- 主机名修改 Oracle监听器,oracle agent不能启动的解决方案
- pycharm安装包时各种报错,且pip无法安装
- Visual Studio 2019 安装教程 附免费安装包资源
- Java实现八皇后问题的解法(一维数组版本)
- Matlab | matpower5.0:最优潮流执行步骤
- 计算机视觉与深度学习 | K-means聚类算法在计算机视觉中的应用之图像分割
- Windows消息:WM_USER与WM_APP的区别
- eclipse java 运行快捷键_java – 可以使用Eclipse中的键盘快捷方式启动/停止Tomcat吗?...