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

本文共 5348 字,大约阅读时间需要 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
    @EnableAspectJAutoProxy
    public class AOPConfig {}
  • XML方式配置

切面声明

@Component
@Aspect
public 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的location匹配规则的关键问题详解
查看>>
Nginx的Rewrite正则表达式,匹配非某单词
查看>>
Nginx的使用总结(一)
查看>>
Nginx的使用总结(三)
查看>>
Nginx的使用总结(二)
查看>>
Nginx的可视化神器nginx-gui的下载配置和使用
查看>>
Nginx的是什么?干什么用的?
查看>>
Nginx访问控制_登陆权限的控制(http_auth_basic_module)
查看>>
nginx负载均衡和反相代理的配置
查看>>
nginx负载均衡器处理session共享的几种方法(转)
查看>>
nginx负载均衡的5种策略(转载)
查看>>
nginx负载均衡的五种算法
查看>>
nginx转发端口时与导致websocket不生效
查看>>
Nginx运维与实战(二)-Https配置
查看>>
Nginx配置Https证书
查看>>
Nginx配置ssl实现https
查看>>
Nginx配置TCP代理指南
查看>>
Nginx配置——不记录指定文件类型日志
查看>>
nginx配置一、二级域名、多域名对应(api接口、前端网站、后台管理网站)
查看>>
Nginx配置代理解决本地html进行ajax请求接口跨域问题
查看>>