博客
关于我
Spring Framework之AOP
阅读量:429 次
发布时间:2019-03-06

本文共 5247 字,大约阅读时间需要 17 分钟。

Spring Framework 之 AOP

目录


AOP概述

AOP(Aspect-Oriented Programming,面向切面编程)是一种软件开发方法,旨在通过横切关注点(Aspect)来提升代码的可维护性和复用性。与传统的面向对象编程相比,AOP允许开发者关注业务逻辑之外的其他常见任务,如日志记录、权限控制、事务管理等。

在现实编程中,许多系统功能的实现都会重复出现类似的代码逻辑。例如,鉴权模块、监控模块、日志记录模块等,这些功能在业务逻辑中难以通过纵向抽象来实现。AOP通过横向抽取机制,将这些分散的代码逻辑集中到独立的模块中,实现了“单一职责”的思想。


AOP知识

1. 连接点(Joinpoint)

程序执行的某个特定位置,例如类初始化前后、函数调用前后、函数抛异常后等。连接点具有边界性质,能够明确区分代码的执行边界。

2. 切点(Pointcut)

切点是用于定位特定连接点的规则。通过点剪切规则,可以为目标类中的特定连接点添加增强逻辑,而不需要为每个类或函数添加Advice。

3. 增强(Advice)

增强是指在特定的连接点上插入额外的逻辑。增强可以是前置逻辑、后置逻辑或环绕逻辑。

4. 目标对象(Target)

目标对象是指被织入增强逻辑的对象。通过动态代理或字节码增强技术,将增强逻辑织入目标类。

5. 引介(Introduction)

引介是一种特殊的增强,用于为类或方法添加新的属性和方法。例如,可以通过引介为目标类中添加一些辅助方法。

6. 织入(Weaving)

织入是指将增强逻辑添加到目标类的连接点上的过程。通过动态代理或字节码技术,将增强逻辑与目标类的业务逻辑编织在一起。

7. 代理(Proxy)

在AOP中,目标类被织入增强后会生成一个新的代理类。代理类结合了原类和增强逻辑,通过动态代理技术实现对目标类方法的拦截和调试。

8. 切面(Aspect)

切面由切点和增强组成,表示系统中的一种横切关注点。Spring AOP负责将切面中的增强逻辑织入指定的连接点中。


代理

静态代理

静态代理是在编译时生成的代理类,通过继承或组合的方式实现对目标对象的代理。静态代理的优点是性能较高,但缺点是实现复杂度较高,且只能针对接口实现。

代理模式

代理模式通过引入一个代理对象,间接地访问目标对象,实现对目标对象功能的扩展或增强。以下是一个简单的静态代理示例:

public interface Subject {    void request();}public class RealSubject implements Subject {    public void request() {        // 业务逻辑    }}public class Proxy implements Subject {    private Subject subject;    public Proxy(Subject subject) {        this.subject = subject;    }    public void request() {        // 预处理逻辑        this.subject.request();        // 后处理逻辑    }}

动态代理

动态代理是在运行时动态生成的代理类,适用于没有接口定义或需要频繁创建代理对象的情况。动态代理分为JDK动态代理和CGLIB动态代理。

JDK动态代理

JDK动态代理基于反射机制,通过动态生成代理类来实现目标类的方法拦截。以下是一个简单的JDK动态代理示例:

public class Monitor {    public static void begin() {        System.out.println("开始");    }    public static void end() {        System.out.println("结束");    }}public interface CouponService {    void getCoupon();}public class CouponServiceImpl implements CouponService {    public void getCoupon() {        Monitor.begin();        try {            System.out.println("业务代码");        } catch (Exception e) {            throw new RuntimeException(e);        }        Monitor.end();    }}public class PerformanceHandler implements InvocationHandler {    private Object target;    public PerformanceHandler(Object target) {        this.target = target;    }    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        Monitor.begin();        Object result = method.invoke(target, args);        Monitor.end();        return result;    }}public class Client {    public static void main(String[] args) {        CouponService target = new CouponServiceImpl();        PerformanceHandler performanceHandler = new PerformanceHandler(target);        CouponService proxy = (CouponService) Proxy.newProxyInstance(            target.getClass().getClassLoader(),            target.getClass().getInterfaces(),            performanceHandler        );        proxy.getCoupon();    }}

CGLIB动态代理

CGLIB动态代理通过字节码技术为目标类生成子类,从而实现方法拦截和增强。以下是一个简单的CGLIB动态代理示例:

public class CglibProxy implements MethodInterceptor {    private Enhancer enhancer = new Enhancer();    public Object getProxy(Class clazz) {        enhancer.setSuperclass(clazz);        enhancer.setCallback(this);        return enhancer.create();    }    @Override    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {        System.out.println("前置逻辑");        Object result = methodProxy.invokeSuper(o, objects);        System.out.println("后置逻辑");        return result;    }}public class Client {    public static void main(String[] args) {        CglibProxy proxy = new CglibProxy();        CouponServiceImpl service = (CouponServiceImpl) proxy.getProxy(CouponServiceImpl.class);        service.getCoupon();    }}

静态代理与动态代理区别

  • 静态代理:在编译时就生成代理类,编译完成后直接使用。
  • 动态代理:在运行时动态生成代理类,需要加载到JVM中。

JDK动态代理与CGLIB动态代理区别

  • CGLIB动态代理:适合需要频繁创建代理对象或目标类没有接口定义的情况。
  • JDK动态代理:适合需要动态代理多个接口的情况。

AspectJ

AspectJ是一种基于Java注解的AOP框架,能够在编译阶段将切面逻辑织入目标类中。以下是AspectJ的基本知识:

切面定义

  • Java Configuration方式配置

    @Configuration@EnableAspectJAutoProxypublic class AOPConfig {}
  • XML方式配置

切面声明

@Component@Aspectpublic class ControllerIntercept {    @Pointcut("execution(public * com.ljw.controller.DiscernController.discern(..))")    public void discernWeb() {}}

切点声明

@Pointcut("execution(public * com.ljw.discern_spider.controller.DiscernController.discern(..))")public void discernWeb() {}

增强声明

@Around("discernWeb()")public Object around(ProceedingJoinPoint joinPoint) {    long start = System.currentTimeMillis();    try {        before(joinPoint);        return joinPoint.proceed(joinPoint.getArgs());    } catch (Throwable t) {        return Result.createFalseRet().withErrMsg("around exception");    }}

常见问题

AOP的实现方式有哪些?

  • 基于AspectJ的注解驱动开发:通过Java注解定义切面和切点。
  • 基于动态代理的实现:通过JDK动态代理或CGLIB动态代理实现横切逻辑。

Spring AOP 与 AspectJ AOP的区别?

  • Spring AOP:基于动态代理实现,支持多种AOP框架。
  • AspectJ AOP:基于编译时织入,支持更强大的AOP功能。

什么是AOP?

AOP是面向切面编程的一种技术,通过横切关注点实现对系统功能的统一管理。

AOP的好处是什么?

  • 提高代码的可维护性和复用性。
  • 便于对系统功能进行统一管理和扩展。
  • 减少代码冗余,提升开发效率。

转载地址:http://qgtkz.baihongyu.com/

你可能感兴趣的文章
Nginx配置——不记录指定文件类型日志
查看>>
Nginx配置代理解决本地html进行ajax请求接口跨域问题
查看>>
Nginx配置参数中文说明
查看>>
Nginx配置好ssl,但$_SERVER[‘HTTPS‘]取不到值
查看>>
Nginx配置如何一键生成
查看>>
Nginx配置实例-负载均衡实例:平均访问多台服务器
查看>>
NIFI1.21.0通过Postgresql11的CDC逻辑复制槽实现_指定表多表增量同步_增删改数据分发及删除数据实时同步_通过分页解决变更记录过大问题_02----大数据之Nifi工作笔记0054
查看>>
NIFI从MySql中增量同步数据_通过Mysql的binlog功能_实时同步mysql数据_配置binlog_使用处理器抓取binlog数据_实际操作01---大数据之Nifi工作笔记0040
查看>>
NIFI从MySql中增量同步数据_通过Mysql的binlog功能_实时同步mysql数据_配置数据路由_实现数据插入数据到目标数据库_实际操作03---大数据之Nifi工作笔记0042
查看>>
NIFI同步MySql数据_到SqlServer_错误_驱动程序无法通过使用安全套接字层(SSL)加密与SQL Server_Navicat连接SqlServer---大数据之Nifi工作笔记0047
查看>>
Nifi同步过程中报错create_time字段找不到_实际目标表和源表中没有这个字段---大数据之Nifi工作笔记0066
查看>>
NIFI大数据进阶_离线同步MySql数据到HDFS_02_实际操作_splitjson处理器_puthdfs处理器_querydatabasetable处理器---大数据之Nifi工作笔记0030
查看>>
NIFI大数据进阶_连接与关系_设置数据流负载均衡_设置背压_设置展现弯曲_介绍以及实际操作---大数据之Nifi工作笔记0027
查看>>
NIFI数据库同步_多表_特定表同时同步_实际操作_MySqlToMysql_可推广到其他数据库_Postgresql_Hbase_SqlServer等----大数据之Nifi工作笔记0053
查看>>
NIFI汉化_替换logo_二次开发_Idea编译NIFI最新源码_详细过程记录_全解析_Maven编译NIFI避坑指南001---大数据之Nifi工作笔记0068
查看>>
NIFI集群_内存溢出_CPU占用100%修复_GC overhead limit exceeded_NIFI: out of memory error ---大数据之Nifi工作笔记0017
查看>>
NIH发布包含10600张CT图像数据库 为AI算法测试铺路
查看>>
Nim游戏
查看>>
NIO ByteBuffer实现原理
查看>>
Nio ByteBuffer组件读写指针切换原理与常用方法
查看>>