博客
关于我
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/

你可能感兴趣的文章
npm切换到淘宝源
查看>>
npm切换源淘宝源的两种方法
查看>>
npm前端包管理工具简介---npm工作笔记001
查看>>
npm包管理深度探索:从基础到进阶全面教程!
查看>>
npm升级以及使用淘宝npm镜像
查看>>
npm发布包--所遇到的问题
查看>>
npm发布自己的组件UI包(详细步骤,图文并茂)
查看>>
npm和package.json那些不为常人所知的小秘密
查看>>
npm和yarn清理缓存命令
查看>>
npm和yarn的使用对比
查看>>
npm如何清空缓存并重新打包?
查看>>
npm学习(十一)之package-lock.json
查看>>
npm安装 出现 npm ERR! code ETIMEDOUT npm ERR! syscall connect npm ERR! errno ETIMEDOUT npm ERR! 解决方法
查看>>
npm安装crypto-js 如何安装crypto-js, python爬虫安装加解密插件 找不到模块crypto-js python报错解决丢失crypto-js模块
查看>>
npm安装教程
查看>>
npm报错Cannot find module ‘webpack‘ Require stack
查看>>
npm报错Failed at the node-sass@4.14.1 postinstall script
查看>>
npm报错fatal: Could not read from remote repository
查看>>
npm报错File to import not found or unreadable: @/assets/styles/global.scss.
查看>>
npm报错TypeError: this.getOptions is not a function
查看>>