Spring4详解系列(四)面向切面的Spring
1、什么是面向切面编程
AOP(Aspect-Oriented Programming), 即面向切面编程, 它与 OOP( Object-Oriented Programming, 面向对象编程) 相辅相成, 提供了与 OOP 不同的抽象软件结构的视角,也可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。OOP引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力。也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系,而AOP技术则恰恰相反,它利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,即方面。使用“横切”技术。
AOP把软件系统分为两个部分:核心关注点(核心业务逻辑)和横切关注点(横向的通用逻辑)。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处都基本相似。比如权限认证、日志、事务处理。
2、Spring对AOP的支持
Spring提供了四种类型的AOP支持
- 经典的基于代理的AOP
- @AspectJ注解驱动的切面
- 纯POJO切面
- 注入式AspectJ切面
前三种都是Spring AOP现实的变体、Spring AOP构建在动态代理的基础之上、因此,Spring对AOP的支持局限于方法拦截
3、AOP的相关概念
1.通知(Advice) 通知定义了在切入点代码执行时间点附近需要做的工作。
Spring支持五种类型的通知:
- @Before(前置通知) org.apringframework.aop.MethodBeforeAdvice
- @AfterReturning(后置通知) org.springframework.aop.AfterReturningAdvice
- @AfterThrowing(异常抛出) org.springframework.aop.ThrowsAdvice
- @Arround(环绕通知) org.aopaliance.intercept.MethodInterceptor
- @Introduction(引入) org.springframework.aop.IntroductionInterceptor
2.连接点(Joinpoint) 程序能够应用通知的一个“时机”,这些“时机”就是连接点,例如方法调用时、异常抛出时、方法返回后等等。
3.切入点(Pointcut) 通知定义了切面要发生的“故事”,连接点定义了“故事”发生的时机,那么切入点就定义了“故事”发生的地点,例如某个类或方法的名称,Spring中允许我们方便的用正则表达式来指定。
4.切面(Aspect) 通知、连接点、切入点共同组成了切面:时间、地点和要发生的“故事”。
5.引入(Introduction) 引入允许我们向现有的类添加新的方法和属性(Spring提供了一个方法注入的功能)。
6.目标(Target) 即被通知的对象,如果没有AOP,那么通知的逻辑就要写在目标对象中,有了AOP之后它可以只关注自己要做的事,解耦合!
7.代理(proxy) 应用通知的对象,详细内容参见设计模式里面的动态代理模式。
8.织入(Weaving) 把切面应用到目标对象来创建新的代理对象的过程,织入一般发生在如下几个时机:
- 编译时:当一个类文件被编译时进行织入,这需要特殊的编译器才可以做的到,例如AspectJ的织入编译器;
- 类加载时:使用特殊的ClassLoader在目标类被加载到程序之前增强类的字节代码;
- 运行时:切面在运行的某个时刻被织入,SpringAOP就是以这种方式织入切面的,原理应该是使用了JDK的动态代理技术。
4、相关知识点
AOP 有哪些实现方式?
实现 AOP 的技术,主要分为两大类: 静态代理 - 指使用 AOP 框架提供的命令进行编译,从而在编译阶段就可生成 AOP 代理类,因此也称为编译时增强; 编译时编织(特殊编译器实现) 类加载时编织(特殊的类加载器实现)。 动态代理 - 在运行时在内存中“临时”生成 AOP 动态代理类,因此也被称为运行时增强。 JDK 动态代理 CGLIB
Spring AOP and AspectJ AOP 有什么区别?
Spring AOP 基于动态代理方式实现;AspectJ 基于静态代理方式实现。 Spring AOP 仅支持方法级别的 PointCut;提供了完全的 AOP 支持,它还支持属性级别的 PointCut。
如何理解 Spring 中的代理?
将 Advice 应用于目标对象后创建的对象称为代理。在客户端对象的情况下,目标对象和代理对象是相同的。
指出在 spring aop 中 concern 和 cross-cutting concern 的不同之处。
concern 是我们想要在应用程序的特定模块中定义的行为。它可以定义为我们想要实现的功能。cross-cutting concern 是一个适用于整个应用的行为,这会影响整个应用程序。例如,日志记录,安全性和数据传输是应用程序几乎每个模块都需要关注的问题,因此它们是跨领域的问题。
5、使用注释创建切面
@Aspect
@Component
public class Spring4AopConfig {/*** execution 用于匹配方法执行的连接点;* within 用于匹配指定类型内的方法执行;*/
// @Pointcut("within(com.spr.demo.service..*)")
// public void commonServiceLogger(){}@Pointcut(value = "execution(** com.spr.demo.controller.AopCpntroller.*(..))")public void commonExecution(){}@Before("commonExecution()")public void startMethod(JoinPoint point) {System.out.println(point.getSignature().getName() + "前置通知...");}@AfterReturning(pointcut = "commonExecution()",returning="result")public void afterMethod(JoinPoint point,Object result) {System.out.println(point.getSignature().getName() + "后置通知:" + result);}@AfterThrowing(pointcut = "commonExecution()",throwing = "e")public void throwMethod(JoinPoint point, Throwable e) {System.out.println(point.getSignature().getName() + "异常通知:" + e);}/*** joinpoint和proceedingjoinpoint区别* joinpoint:public interface JoinPoint { String toString(); //连接点所在位置的相关信息 String toShortString(); //连接点所在位置的简短相关信息 String toLongString(); //连接点所在位置的全部相关信息 Object getThis(); //返回AOP代理对象 Object getTarget(); //返回目标对象 Object[] getArgs(); //返回被通知方法参数列表 Signature getSignature(); //返回当前连接点签名 SourceLocation getSourceLocation();//返回连接点方法所在类文件中的位置 String getKind(); //连接点类型 StaticPart getStaticPart(); //返回连接点静态部分 } * proceedingjoinpoint:* public interface ProceedingJoinPoint extends JoinPoint { public Object proceed() throws Throwable; public Object proceed(Object[] args) throws Throwable; }JoinPoint.StaticPart:提供访问连接点的静态部分,如被通知方法签名、连接点类型等:public interface StaticPart { Signature getSignature(); //返回当前连接点签名 String getKind(); //连接点类型 int getId(); //唯一标识 String toString(); //连接点所在位置的相关信息 String toShortString(); //连接点所在位置的简短相关信息 String toLongString(); //连接点所在位置的全部相关信息 } 环绕通知 ProceedingJoinPoint 执行proceed方法的作用是让目标方法执行,这也是环绕通知和前置、后置通知方法的一个最大区别。Proceedingjoinpoint 继承了 JoinPoint 。是在JoinPoint的基础上暴露出 proceed 这个方法。proceed很重要,这个是aop代理链执行的方法。*/@Around("commonExecution()")
// public void aroundMethod(ProceedingJoinPoint jp,Throwable e){public void aroundMethod(ProceedingJoinPoint point){try {System.out.println("< 环绕通知开始执行 >...");Object proceed = point.proceed();System.out.println("< 环绕通知执行完成 > : " + point.getSignature().getName() + ","+point.getSignature().getDeclaringTypeName()+","+proceed);} catch (Throwable e) {System.err.println("< 环绕通知异常 > : " + e.getMessage());}}}
如果不想要使用@Component注解加载切面,也可以通过组件加载:
@Configuration
@EnableAspectJAutoProxy
@ComponentScan
public class ConfigCenter {@Beanpublic Spring4AopConfig spring4AopConfig() {return new Spring4AopConfig();}
}
6、通过注解引入新功能
使用@DeclareParents注解,将接口引入到Spring Bean中。
@DeclareParents注解由三部分组成:
1)value属性指定了哪种类型的bean要引入该接口。加号(+)表示是该类型的所有子类型,而不是该类型本身。
2)defaultImpl属性指定了为引入功能提供实现的类。
3)@DeclareParents注解所标注的静态属性指明了要引入的接口。
EncoreableIntroducer是一个切面,同时声明它是一个bean。但是,它与我们 之前所创建的切面不同,它并没有提供前置、后置或环绕通知,而是 通过@DeclareParents注解,将Encoreable接口引入 到Performance bean中:
// 创建一个接口 public interface Encoreable {void performEncore();}// 实现接口 public class DefaultEncoreable implements Encoreable {@Overridepublic void performEncore() {System.out.println("接口实现");} }//新建切面 @Aspect @Component public class EncoreableIntroducer {@DeclareParents(value = "concert2.Performance+", defaultImpl = DefaultEncoreable.class)public static Encoreable encoreable; }
7、注入AspectJ切面
虽然Spring AOP能够满足许多应用的切面需求,但是与AspectJ相比,Spring AOP 是一个功能比较弱的AOP解决方案。AspectJ提供了Spring AOP所不能支持的许多类型的切点。
//定义切面 public aspect CriticAspect {public CriticAspect(){}//定义切点pointcut performance():execution(* perform(..));afterReturning : performance(){System.out.println(criticismEngine.getCriticism());}private CriticismEngine criticismEngine;// 注入criticismEnginepublic void setCriticismEngine(CriticismEngine criticismEngine){this.criticismEngine = criticismEngine;} }public class CriticismEngineImpl extends CriticismEngine {public CriticismEngineImpl(){}private String[] criticismPool;@Overridepublic String getCriticism(){int i = (int)(Math.random() * criticismPool.length);return criticismPool[i];}public void setCriticismPool(String[] criticismPool){this.criticismPool = criticismPool;} }
Spring4详解系列(四)面向切面的Spring相关推荐
- spring(4)面向切面的Spring(AOP)
[0]README 1)本文部分文字描述转自:"Spring In Action(中/英文版)",旨在review "spring(4)面向切面的Spring(AOP) ...
- 《Spring实战》读书笔记-第4章 面向切面的Spring
<Spring实战>是学习Spring框架的一本非常经典的书籍,之前阅读了这本书,只是在书本上写写画画,最近整理了一下<Spring实战>的读书笔记,通过博客的方式进行记录分享 ...
- 面向切面的 Spring —— 什么是面向切面编程?
Q1:面向切面编程(AOP)解决什么问题? A1:把横切关注点与业务逻辑相分离. Q2:什么是横切关注点? A2:在软件开发中,散布于应用中多处的功能. 日志是应用切面的常见范例,但并不是切面适用的唯 ...
- Spring实战 | 第一部分 Spring的核心(第四章 面向切面的Spring)
第四章 面向切面编程 面向切面编程的基本原理 通过POJO创建切面 使用@AspectJ注解 为AspectJ切面注入依赖 AspectJ是一个面向切面的框架,它扩展了java语言.AspectJ定义 ...
- spring boot 503_Spring实战读书笔记第4章 面向切面的Spring
本章内容: 面向切面编程的基本原理 通过POJO创建切面 使用@AspectJ注解 为AspectJ切面注入依赖 在软件开发中,散布于应用中多的功能被称为横切关注点(cross-cutting con ...
- 面向切面的Spring
2019独角兽企业重金招聘Python工程师标准>>> 前言 在软件开发中,散布于应用中多处的功能被称为横切关注点.这些横切关注点从概念上是与应用的业务逻辑相分离的.把这些横切关注点 ...
- 【Spring实战学习笔记】第4章 面向切面的Spring
目录 4.1 什么是面向切面编程 4.2 通过切点来选择连接点 4.3 使用注解创建切面 4.4 在XML中声明切面 4.5 注入AspectJ切面 4.6 小结 在软件开发中,散布于应用中多处的功 ...
- Spring4详解系列(一)Spring之旅
1.Spring的核心 Spring可以做很多事,提供了很多企业级开发的功能,但是这些功能的底层都依赖于它的两个核心特性: ①DI(Dependency Injection)依赖注入,指容器复制创建和 ...
- Handler详解系列(四)——利用Handler在主线程与子线程之间互发消息,handler详解...
MainActivity如下: package cc.c;import android.app.Activity; import android.os.Bundle; import android.o ...
最新文章
- Django之Xadmin
- Pretty girl,你一定要去旅行
- 如何在MVCsheet表单页面的后台取到页面自定义字段的值?
- jdk1.6 改 jdk1.7或jdk1.8(改回也可以)(图文详解)
- oracle如何在本地建库,oracle在本地建库
- FD.io VPP:探究分段场景下vlib_buf在收发包的处理(dpdk_plugin.so)、rte_mbuf与vlib_buf 关系
- strcpy vs memcpy
- springamqp_SpringAMQP
- 穿越沙漠问题c语言算法,穿越沙漠问题---递推法
- 软件测试的底层逻辑是什么?
- Nifi从入门到精通(一)之 数据存储
- win10计算器rsh_win10 自带计算器快捷键有哪些_windows10计算器快捷键汇总
- 组合数计算(从1000到1e9的组合数各类求法)
- Sql 中text类型字段判断是否为空
- 丽丽的redhat终于可以上网了
- QQ 聊天机器人API
- Centos7.5系统部署禅道协调管理系统以及配置优化
- windows11如何退回windows10,手把手,突然觉得我不适合win11
- 在Arcmap中,如何“让标注和注记的字体,以及符号化后的符号大小随着比例尺大小的变换而变换”???
- 关于VC++调试项 Multi-threaded Debug DLL的问题。