AOP 和 动态代理
热门问题
- 什么是 AOP,为什么要使用 AOP ?
- 什么是动态代理?
- 动态代理常用的两种方式?
- jdk的动态代理是如何实现的?
- Cglib如何实现动态代理?
- Spring AOP 和 AspectJ 有什么区别?
- Spring AOP 的常见术语?(了解)
见招拆招
1、什么是 AOP,为什么要使用 AOP ?
AOP 是 Spring 框架的一个核心机制,使用 AOP 能够在不改变原有代码的基础上对原有代码进行扩展和增强,也就是面向切面编程嘛。平时我们在开发的时候,都会定义一个切入点,围绕这个切入点编写一些切面方法,在目标方法执行的前后,或者异常的时候,做统一的处理。AOP 其实就是基于动态代理机制嘛,可以在不修改源码的基础上为现有的代码添加功能。以上就是我对 AOP 的理解。
(这个问题没什么意义,主要是去引出后面那些问题,这里同样埋好了钩子,当然,你不埋,面试官大概率也会问)
2、什么是动态代理?
动态代理主要是我们程序在运行时动态生成代理类的一种机制,让我们在不修改原始类的情况下,可以对原始类进行扩展和增强,主要有两种方式:一种是基于 jdk 的 proxy,另一种是 cglib。
(如果面试官问题是从动态代理起头的,那么你要扯到 AOP 上)
我们平时经常使用的 Spring 框架的 AOP 机制,就是基于动态代理实现的嘛。
(这里抛一个 AOP 的钩子就行了)
3、动态代理常用的两种实现方式?
主要有两种,一种是基于 jdk 的动态代理,另一种是基于 cglib 的动态代理。它们最主要的区别就是 jdk 动态代理主要是依赖于接口创建代理对象,cglib 是通过生成子类的方式,不需要接口,两种方式其实经常配合使用的,当类没有实现接口的时候,就可以通过 cglib 来弥补不足。从性能上来看,因为 jdk 使用反射机制,它的性能相比于 cglib 来说是要稍微逊色一点。cglib 的话,会更占用内存一点。两者都可以满足各种需求,按照有无接口实现的原则进行选择。(如果面试官问你,Spring 默认使用的是什么动态代理时,你就可以给他这么说,最后加上一嘴,在 Spring 配置中,可以通过@EnableAspectJAutoProxy注解的proxyTargetClass属性来强制指定)
(如果这道题打头,还是要先说一下:什么是动态代理?)
4、JDK动态代理是如何实现的?
先看一篇文章:https://blog.csdn.net/weixin_45863010/article/details/144215384
(最好是自己去写一下案例,深刻一点)
jdk 实现动态代理呢,主要是依靠 Proxy静态类 和 InvocationHandler接口。
因为 jdk 动态代理要求类必须有接口嘛,所以肯定是要先定义一个接口,就叫它 MyService 吧:
public interface MyService {
void work();
}
然后让我们的目标类去实现这个MyService
接口:
public class MyServiceImpl implements MyService{
@Override
public void work() {
System.out.println("我要开始工作了");
}
}
这样,代理目标类的准备工作就做好了,之后我们需要编写一个InvocationHandler接口
的实现类,在invoke
方法中编写一些增强逻辑:
public class LoggingInvocationHandler implements InvocationHandler {
private final Object target;
public LoggingInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("进入代理方法了");
Object result;
try {
System.out.println("目标方法执行前");
result = method.invoke(target,args);
System.out.println("目标方法执行后");
}
catch (Exception e){
throw new RuntimeException(e);
}
System.out.println("代理方法 return 之前");
return result;
}
}
最后,通过 Proxy 的静态方法newProxyInstance
就可以创建一个代理对象了:
public class Main {
public static void main(String[] args) {
// 创建目标对象
MyServiceImpl target = new MyServiceImpl();
// 创建代理调用器
LoggingInvocationHandler loggingInvocationHandler =
new LoggingInvocationHandler(target);
// 创建代理对象
MyService proxyInstance = (MyService) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
loggingInvocationHandler
);
// 调用方法
proxyInstance.work();
}
}
以上就是 jdk 动态代理实现的主要步骤了。
(自己写几遍就记住了)
5、Cglib如何实现动态代理?
cglib 实现动态代理其实和 jdk 实现动态代理很相像的,不同的就是 cglib 实现代理时,被代理的类不需要实现某个接口。我简单说一下实现步骤吧:
首先肯定是要去引入cglib
依赖的,然后创建一个目标类:
public class Target {
public void work(){
System.out.println("我又来工作了");
}
}
之后我们需要编写一个MethodInterceptor接口
的实现类,在intercept
方法中编写一些增强逻辑:
public class LoggingMethodInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object target, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("进入代理方法喽");
Object result;
try {
System.out.println("目标方法执行前");
result = methodProxy.invoke(target, args);
System.out.println("目标方法执行后");
}
catch (Exception e){
throw new RuntimeException(e);
}
System.out.println("代理方法 return 前");
return result;
}
}
最后,通过创建Enhancer
对象,设置目标类为代理类的父类,设置对应的方法拦截器,然后就可以创建代理对象了:
public class Main {
public static void main(String[] args) {
// 创建 Enhancer 对象
Enhancer enhancer = new Enhancer();
// 设置目标类为代理类的父类
enhancer.setSuperclass(Target.class);
// 设置方法拦截器
enhancer.setCallback(new LoggingMethodInterceptor());
// 创建代理对象
Target target = (Target) enhancer.create();
// 调用方法
target.work();
}
}
(我的 jdk 版本是17,所以跑不起来)
6、Spring AOP 和 AspectJ 有什么区别?
这两个都是实现 AOP 的两个常见框架,Spring AOP 是 Spring 框架提供的一种 AOP 实现,主要用于运行时的代理机制;AspectJ 支持编译时、类加载时和运行时,相较于 Spring AOP 而言,适用范围更广。平时开发中呢,Spring AOP 足够满足我的日常需求了,对于 AspectJ 这个框架呢,也只是了解了一下,并没有去使用过。
(提前给它说,老子不会 AspectJ)
7、Spring AOP 的常见术语?(了解)
这个问题其实没有啥子意义,那些术语确实抽象,但是保不齐就你了呢,这里贴一篇文章,有一个印象就行了:
https://blog.csdn.net/lhj520cb/article/details/125820513
(确实长啊,这篇文章,最好是你提前写一个简单的切面示例,然后尝试给面试官具象的说一下,这样才直观)
2025/01/04
writeBy kaiven