简介
AOP(Aspect-Oriented Programming):面向切面编程,AOP的主要编程对象是切面,而切面模块化横切关注点.
AOP可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。OOP引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力。也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系。例如日志功能。日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系。对于其他类型的代码,如安全性、异常处理和透明的持续性也是如此。这种散布在各处的无关的代码被称为横切(cross-cutting)代码,在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。
而AOP技术则恰恰相反,它利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,即方面。所谓“方面”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。AOP代表的是一个横向的关系,如果说“对象”是一个空心的圆柱体,其中封装的是对象的属性和行为;那么面向方面编程的方法,就仿佛一把利刃,将这些空心圆柱体剖开,以获得其内部的消息。而剖开的切面,也就是所谓的“方面”了。然后它又以巧夺天功的妙手将这些剖开的切面复原,不留痕迹。
实现AOP的技术,主要分为两大类:一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。
好处:
-每个事物逻辑位于一个位置,代码不分散,便于维护升级
-业务模板更简洁,只包含核心业务代码。
使用场景
| 名称 | 解释 |
|---|---|
| Authentication | 权限 |
| Caching | 缓存 |
| Context passing | 内容传递 |
| Error handling | 错误处理 |
| Lazy loading | 懒加载 |
| Debugging | 调试 |
| logging, tracing, profiling and monitoring | 记录跟踪 优化 校准 |
| Performance optimization | 性能优化 |
| Persistence | 持久化 |
| Resource pooling | 资源池 |
| Synchronization | 同步 |
| Transactions | 事务 |
概念
切面 Aspect:横切关注点被模块化的特殊对象
**通知**Advice:切面必须完成的工作
**目标**Target:被通知的对象
**代理**Proxy:向目标对象 应用通知之后创建的对象
**连接点J**oinpoint:程序执行的某个特定位置
切点*pointcut:每个类都拥有多个连接点,即连接点是程序类中客观存在的事物,AOP通过切点定位到特定的连接点。类比:连接点相当于数据库中的记录,切点相当于查询条件。*指定一个通知将被引发的一系列连接点的集合。AOP框架必须允许开发者指定切入点:例如,使用正则表达式。 Spring定义了Pointcut接口,用来组合MethodMatcher和ClassFilter,可以通过名字很清楚的理解, MethodMatcher是用来检查目标类的方法是否可以被应用此通知,而ClassFilter是用来检查Pointcut是否应该应用到目标类上
入门例子,前置通知
场景:在每次调用add,multiply方法前做某些操作,类似日志记录。
package com.test.aop;
public interface Calculation {
int add(int x,int y);
int multiply(int x,int y);
}
package com.test.aop;
import org.springframework.stereotype.Component;
@Component
public class CalculationImpl implements Calculation {
@Override
public int add(int x, int y) {
return x+y;
}
@Override
public int multiply(int x, int y) {
return x*y;
}
}
切面类
package com.test.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
//注解表示切面
@Aspect
@Component
public class LoggingAspect {
//前置通知,匹配相应的方法
@Before("execution(public int com.test.aop.CalculationImpl.*(int, int))")
public void beforeMethod(JoinPoint joinpoint){
String methodName=joinpoint.getSignature().getName();
List<Object> params= Arrays.asList(joinpoint.getArgs());
System.out.println("The method is "+methodName+" params are "+params);
}
}
测试运行类Main
package com.test.aop;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args){
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
Calculation calculation=applicationContext.getBean(Calculation.class);
int result=calculation.add(3,4);
System.out.println("result="+result);
}
}
spring配置文件:applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="com.test.aop"></context:component-scan>
<!--使Aspectj起作用-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
运行结果:
The method is add params are [3, 4]
result=7
本文详细介绍了面向切面编程(AOP)的概念及其与面向对象编程(OOP)的区别,阐述了AOP如何通过模块化横切关注点来提高代码的可维护性和可重用性。同时,列举了AOP在实际开发中的应用场景,并通过一个具体示例展示了如何在Spring框架下实现AOP。
268

被折叠的 条评论
为什么被折叠?



