OOP的完美点缀—AOP之SpringAOP实现原理
OOP的完美点缀—AOP之SpringAOP实现原理
前言
OOP与AOP
OOP(Object Oriented Programming,面向对象编程),通过封装、继承将程序抽象为各个层次的对象,进而组合为模块或者程序,达到了软件工程中的重用性、灵活性、扩展性。程序的运行笼统地可以看为各层次对象之间的相互调用。
AOP(Aspect Oriented Programming,面向切面编程),将程序运行过程分解为一个个的切面,对特定的切面(某个步骤或者阶段)进行提取,达到解耦各种不同逻辑代码。
OOP是在程序分块层面上进行考虑,而AOP则是在程序运行的切面上进行考虑。
可以将AOP理解为一种无损伤型的”切面”激光手术刀。OOP使属性和行为被封装为了一个严实、密不透风的对象。想要改变由对象保护着的方法,就可以通过该激光手术刀,既不损伤对象(即是,不破坏对象的封装),又不添加任何冗余的代码,实现对原对象的方法的增强处理。
不得不说,AOP实在是一种巧妙的编程思想!!!弥补了OOP中一些难以解决的问题。例如,
1. 类应该是纯净的,不应含有与本身无关的逻辑。如日志跟踪的逻辑代码。这样的类就可以更好地重用,更有效地被AOP的切入更多的业务逻辑, 举例代码如下:
/*
* 假如需要记录某只柯基狗的日常,
* 我们总不能让它自己来记录吧??
* 如 下面的注释了的方法
* 看起来是不是非常怪异,一只狗狗自己给自己写日记
*/
class dog{
void run(){
/*note.write("散步了");*/
}
void sleep(){
/*note.write("又睡懒觉了");*/
}
}
2. OOP为不同类别的对象引入公共方法时,往往力不从心,造成大量的分散的重复代码,重用性真的很差,每次都要改动真的很麻烦。
class dog{
private Note note = new Note();
void run(){
note.write("散步了");
}
void sleep(){
note.write("又睡懒觉了");
}
}

本文中”特定处理”指的日志记录、事务管理、异常处理等等之类的各种通用的业务逻辑
AOP实现原理
主要分为两大类:
一是采用动态代理,对被代理对象和特定处理进行修饰和封装,得到代理对象,从使得被代理对象中不需切入任何的代码,如图:
简单的代理:实现不入侵原始对象而切入各种通用的业务逻辑(eg: 参数验证、日志记录方法等)
interface Interface{
void doSomething();
}
/*原始对象*/
class RealObject implements Interface{
@Override
public void doSomething() {
System.out.println("原始对象的行为");
}
}
/*代理*/
class SimplProxy implements Interface {
private Interface proxied;
public SimplProxy(Interface proxied){
this.proxied = proxied;
}
public void doSomething(){
System.out.println("处理一些通用的业务逻辑, 如参数校验等等");
proxied.doSomething();
}
}
/*调用者*/
class Caller{
public static void call(Interface iface){
iface.doSomething();
}
public static void main(String[] args){
call(new SimplProxy(new RealObject()));
}
}
/*输出:*/
1.处理一些通用的业务逻辑, 如参数校验等等
2.原始对象的行为
就这样,一些通用的业务逻辑被代理简单地切入到了原始对象之前执行
二是采用静态织入,如AspectJ,使用其特定的语法创建切面,在编译期间将切面织入代码中。又如,通过AspectJ编译出来的class文件与普通编译出来的有很大区别,这块没有了解,不再赘述。
AOP使用场景
权限控制、异常处理、缓存、事务管理、日志记录、数据校验等等
AOP基本概念
- 切面(Aspect): 程序运行过程中的某个的步骤或者阶段
- 连接点(Joinpoint): 程序运行过程中可执行特定处理(增强处理)的点, 如异常处理。而在SpringAOP中,方法调用是连接点。
- Advice(通知、处理、增强处理): 在符合的连接点进行的特定处理 (增强处理)
- 切入点(Pointcut): 可切入进行增强处理的连接点。AOP核心之一就是如何用表达式来定义符合的切入点。在Spring中,默认使用AspectJ的切入点语法。
由于Spring AOP只支持以Spring Bean的方法调用来作为连接点, 所以在这里切入点的定义包括:- 切入点表达式, 来限制该能作用的范围大小,即是,能匹配哪些bean的方法
- 命名切入点
@Pointcut("execution(* com.xxx.xxx.service.*.* (..)) ") /*切入点*/
public void pointCutExpress(){ /*命名切入点*/
}
/*常见的 切入点表达式语法 如下:*/
execution(返回值类型 方法所属类.方法名 方法形参列表 抛出的异常声明)
例如:
上面第一个 * 指匹配所有返回值类型
第二个 * 指service包下的所有类
第三个 * 指各个类中的所有方法
(..)中的 .. 指零个或者多个(任意数量)的参数
- 目标对象: 被进行增强处理的对象
- AOP代理: 是一个重新封装了(增强处理 + 被代理对象的方法 )方法的代理对象。
- 织入(Weaving): 就如它名字表述的一样,增强处理切入目标对象以后,并获得代理对象(AOP代理)的这个过程,就是织入。按其作用的时间分类为,编译时织入与运行时织入。
SpringAOP的使用方法
基于注解的零配置方式:
一、启动@AspectJ注解支持,旭在相应的容器内,加入如下片段:
<beans xmlns:aop="http://www.springframework.org/schema/aop" <!-- 必须有相应的XML Schema 配置 -->
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
<!-- 必须相应的容器内,启动@AspectJ支持,如对Springmvc的Contrller织入, 则应在Springmvc.xml中配置 -->
<aop:aspectj-autoproxy />
<!-- 扫描相应的包 -->
二、定义切面bean
@Aspect
@Compement
public class Advice{
/*定义切入点, 业务处理逻辑等等其他内容*/
}
三、定义@Before、@After、@Around等增强处理
/*定义切入点表达式*/
/*配置匹配service包下所有的类、所有的方法*/
@Pointcut("execution(* com.xxx.xxx.service.*.*(..))")
public void pointCutExpress(){
}
四、定义处理方法
@After("pointCutExpress()")
public void closeResource(){
/*After注解,更适合于释放资源*/
}
通过注解和动态代理实现简单AOP
一、切入点注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyPointCut {
/*模拟简单的注解定义切入点*/
public String expression();
}
二、原始对象及接口
interface SomeMethods{
void method1();
void method2(String args);
}
public class Implementation implements SomeMethods{
@Override
public void method1() {
System.out.println("原始对象的方法1");
}
@Override
public void method2(String args) {
System.out.println("原始对象的方法2及参数:" + args);
}
}
三、动态代理工厂
class MyAspect{
@MyPointCut(expression = "com.auhnayuil.comm.Implementation.*")
public void Logger(){
System.out.println(">>>>>>>>>>>>>>>>>正在记载日志中<<<<<<<<<<<<<<<<<<<<<<<");
}
}
class SimpleProxyFactory{
/*简单代理工厂*/
public static Object getProxyObject(final Object realObject, final Object aspectObject){/*代理对象 切面定义类*/
final Class<?> realObjectClass = realObject.getClass();
final Class<?> aspectObjectClass = aspectObject.getClass();
return Proxy.newProxyInstance(
realObjectClass.getClassLoader(),
realObjectClass.getInterfaces(),
new InvocationHandler(){
/*模拟简单的@Before日志注解*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
/*加载切入点信息. 这里的方法Logger被硬编码了, 后期可以根据注解来解决*/
Method pointCutMethod = aspectObjectClass.getMethod("Logger", new Class[] {});
MyPointCut myPointCut = pointCutMethod.getAnnotation(MyPointCut.class);
/*判断切入点, 并执行其方法*/
String expression = myPointCut.expression();
String[] express = expression.split("\\.");
int exprLength = express.length;
if("*".equals(express[exprLength - 1])){
/*这里只演示一种情况*/
pointCutMethod.invoke(aspectObject, new Class[] {});
}
/*执行原始对象的方法*/
return method.invoke(realObject, args);
}
}
);
}
}
public class ProxyDemo {
public static void main(String[] args){
SomeMethods someMethods = new Implementation();
SomeMethods proxyObject = (SomeMethods) SimpleProxyFactory.getProxyObject(someMethods, new MyAspect());
proxyObject.method1();
proxyObject.method2("auhnayuiL");
}
}
四、输出结果
>>>>>>>>>>>>>>>>>正在记载日志中<<<<<<<<<<<<<<<<<<<<<<<
原始对象的方法1
>>>>>>>>>>>>>>>>>正在记载日志中<<<<<<<<<<<<<<<<<<<<<<<
原始对象的方法2及参数:auhnayuiL
OOP的完美点缀—AOP之SpringAOP实现原理的更多相关文章
- Java AOP的底层实现原理
Java AOP的底层实现原理 一.什么是AOP 1.AOP:Aspect Oriented Programming(面向切面编程),OOP是面向对象编程,AOP是在OOP基础之上的一种更高级的设计思 ...
- Spring AOP的底层实现原理
Spring的两大核心之一就是AOP,AOP:面向切面编程.在说原理之前,得先知道一些 AOP的专业术语. AOP的专业术语 连接点(JoinPoint):增强执行的位置(增加代码的位置),Sprin ...
- AutoRegister ASM AOP 字节码 案例 原理 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- 从壹开始前后端分离 40 || 完美基于AOP的接口性能分析
旁白音:本文是不定时更新的.net core,当前主线任务的Nuxt+VueAdmin教程的 nuxt.js 之 tibug项目已上线,大家可以玩一玩:http://123.206.33.109:70 ...
- Spring aop 原始的工作原理的理解
理解完aop的名词解释,继续学习spring aop的工作原理. 首先明确aop到底是什么东西?又如何不违单一原则并实现交叉处理呢? 如果对它的认识只停留在面向切面编程,那就脏了.从oop(Objec ...
- springAOP配置原理
什么是AOP AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善.OOP引入 ...
- spring框架学习笔记4:SpringAOP实现原理
AOP AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善.OOP引入 ...
- Spring面试,IoC和AOP的理解, @Transactional原理及使用
spring 的优点?1.降低了组件之间的耦合性 ,实现了软件各层之间的解耦 2.可以使用容易提供的众多服务,如事务管理,消息服务等 3.容器提供单例模式支持 4.容器提供了AOP技术,利用它很容易实 ...
- AOP的定义和原理
一.本课目标 理解Spring AOP的原理 掌握Spring AOP的七个术语 二.面向切面编程(AOP) AOP的思想是,不去动原来的代码,而是基于原来代码产生代理对象,通过代理的方法,去包装原 ...
随机推荐
- 如何让 Git 忽略掉文件中的特定行内容?
近期在git遇到几个问题,让我重新认识到git的强大性,下面列出来记录一下 有一个数据库的配置文件,在用 git add 添加到 index file 时不能透露了相关配置.而如果用 .gitigno ...
- Python thread local
由于GIL的原因,笔者在日常开发中几乎没有用到python的多线程.如果需要并发,一般使用多进程,对于IO Bound这种情况,使用协程也是不错的注意.但是在python很多的网络库中,都支持多线程, ...
- WPF移动Window窗体(鼠标点击左键移动窗体自定义行为)
XAML代码部分:1.引用System.Windows.Interactivity 2.为指定的控件添加一个拖动的行为 3.很简单的了解行为的作用和用法 <Window xmlns=" ...
- 用phpcms如何将静态页面制作成企业网站(下)
上篇讲到了子页部分 这样的 有分页选择 列表项的代码部分 最后输出变量pages就可以了 看一下运行的效果 点击下一页 再来改一下子页显示的样式 点击人才将会出来的一个子页面 路径要统一 再来更改后台 ...
- MySQL · 引擎特性 · InnoDB IO子系统
前言 InnoDB做为一款成熟的跨平台数据库引擎,其实现了一套高效易用的IO接口,包括同步异步IO,IO合并等.本文简单介绍一下其内部实现,主要的代码集中在os0file.cc这个文件中.本文的分析默 ...
- debian+nginx配置初探--php环境、反向代理和负载均衡
配置nginx的PHP环境 安装nginx sudo apt-get install nginx 安装nginx就可以通过下面地址来访问了:http://localhost/ 安装php sudo a ...
- Java并发之线程异常捕获
由于线程的本质特性,使得你不能捕获从线程中逃逸的异常,如: import java.util.concurrent.ExecutorService; import java.util.concurre ...
- Eclipse打JAR包的使用
编译Java代码你当然可以直接使用Javac,但对于大多同学还是使用Eclipse编辑器来得快捷.这篇文章来说说我使用Eclipse编译后的执行之路,走路许多弯路,看我一一道来. 演示系统的架构 首先 ...
- 好多鱼 Java
牛客网的题目: 链接:https://www.nowcoder.com/questionTerminal/e3dd485dd23a42899228305658457927牛牛有一个鱼缸.鱼缸里面已经有 ...
- git 关键词扩展
用习惯了svn 的 关键词扩展.自然在git上也会寻找. 不知道啥是svn的关键词扩展? 简单列举下: 对于subversion来说,一些版本信息是不需要手动添加的,subversion提供了关键字替 ...