1、类加载器
类加载器(Class Loader)负责将JVM中的字节码转化为能够被JVM执行的类,在JVM运行时,会根据需要动态创建类,启动类加载器会首先加载程序中的核心类库,然后通过双亲委派模型逐层向下加载依赖类。类加载器可以分为三种:启动类加载器、扩展类加载器和应用程序类加载器
2、反射
Java中的反射机制是指在运行时动态地获取一个类的信息,包括类的方法、属性、构造函数等,而不需要事先知道这个类的具体实现。通过反射机制,可以在程序运行时获取类的信息,并且可以在运行时调用类的方法、创建对象等
反射机制主要包含以下几个核心类:Class,Constructor,Method,Field
JDK代理使用的是反射机制实现aop的动态代理,CGLIB代理使用字节码处理框架asm
3、AOP
AOP实现原理
AOP是面向切面编程,横向关注点,在切点前后做一些操作,比如日志,注解实现分布式锁等
静态AOP和动态AOP,静态AOP是在编译阶段将切面代码直接以字节码的方式编译到目标字节码文件中,动态AOP是在运行时,为接口动态生成代理类或将切面逻辑加到子类中实现代理的创建和切入点植入;
spring框架中,AOP通过使用AspectJAwareAdvisorAutoProxyCreator这个bean后置处理器实现的,在bean初始化前后进行一些操作,比如判断是否为该bean生成代理对象,并获取advisors然后创建Aop代理对象,并替换原来生成的bean
具体的,如果代理对象实现了某个接口,使用JDK proxy创建代理对象;如果没有实现接口的对象,使用CGlib生成被代理对象子类作为代理
AOP和动态代理的关系
Spring AOP的本质就是动态代理
JDK动态代理依赖一个类和一个接口,分别是什么?
Proxy类和InvocationHandler接口。
JDK动态代理和cglib动态代理有什么区别?
1、JDK动态代理对实现了接口的类生成代理对象,具体说动态实现接口类,在动态生成的实现类里面委托hanlder去调用原始实现类方法
cglib可以对任意类生成代理对象,它的原理是对目标对象进行继承代理,如果目标对象被final修饰,那么该类无法被cglib代理。
2、JDK代理使用的是反射机制实现aop的动态代理,CGLIB代理使用字节码处理框架asm,通过修改字节码生成子类。所以jdk动态代理的方式创建代理对象效率较高,执行效率较低,cglib创建效率较低,执行效率高;
jdk动态代理代码示例:
// 实现InvocationHandler接口
class MyInvocationHandler implements InvocationHandler {
// 声明一个私有变量
private Object target;
// 构造函数
public MyInvocationHandler(Object target) {
this.target = target;
}
// 实现InvocationHandler接口的invoke方法,该方法在代理对象调用方法时被触发。
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("动态代理前置操作");
Object result = method.invoke(target, args);
System.out.println("动态代理后置操作");
return result;
}
}
public class DynamicProxyExample {
public static void main(String[] args) {
// 创建目标对象
UserService userService = new UserServiceImpl();
// 创建InvocationHandler实例
MyInvocationHandler handler = new MyInvocationHandler(userService);
// 创建动态代理对象
UserService proxy = (UserService) Proxy.newProxyInstance(
userService.getClass().getClassLoader(),
userService.getClass().getInterfaces(),
handler
);
// 通过代理对象调用方法
proxy.addUser("Alice");
}
}
cglib代理示例
-- 依赖:
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
public class TargetClass {
public void doSomething() {
// 目标类的具体实现
}
}
public class MyInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
// 在调用目标类方法前进行一些额外的操作
// ...
Object result = proxy.invokeSuper(obj, args);
// 在调用目标类方法后进行一些额外的操作
// ...
return result;
}
}
public class CGLibProxy {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(TargetClass.class);
enhancer.setCallback(new MyInterceptor());
TargetClass proxy = (TargetClass) enhancer.create();
proxy.doSomething();
}
}
Springboot 中的 AOP 实现是基于 JDK 还是 CGLib?
-
如果代理对象有接口,就用 JDK 动态代理
-
如果代理对象没有接口,那么就直接是 Cglib 动态代理。
自动装配
@Configuration
@ConditionalOnClass({ EnableAspectJAutoProxy.class, Aspect.class, Advice.class, AnnotatedElement.class })
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = false)
public static class JdkDynamicAutoProxyConfiguration {
}
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true)
public static class CglibAutoProxyConfiguration {
}
}