CGLIB动态代理和JDK动态代理是两种不同的代理实现方式,它们有一些区别和各自的优缺点。
区别:
1. 实现方式:CGLIB动态代理通过继承被代理类来创建代理类,而JDK动态代理通过实现被代理接口来创建代理类。
2. 支持的代理对象类型:CGLIB动态代理可以代理任意类,而JDK动态代理只能代理实现了接口的类。
3. 性能:CGLIB动态代理在创建代理类时需要使用ASM字节码操作库来修改字节码,相比之下,JDK动态代理的创建过程更加简单,性能略好一些。
优点和缺点:
CGLIB动态代理的优点:
1. 可以代理任意类,不需要被代理类实现接口。
2. 在方法调用前后可以添加额外的逻辑,实现更加灵活的方法拦截和增强。
CGLIB动态代理的缺点:
1. 由于是通过继承被代理类来创建代理类,因此无法代理被标记为final的类和方法。
2. 由于使用了字节码操作,创建代理类的过程相对较慢,性能较差。
JDK动态代理的优点:
1. 创建代理类的过程相对简单,性能较好。
2. JDK动态代理是Java自带的标准库,无需额外依赖。
JDK动态代理的缺点:
1. 只能代理实现了接口的类,无法代理未实现接口的类。
2. 在方法调用前后添加额外的逻辑的能力相对较弱。
综上所述,CGLIB动态代理适用于代理任意类,对性能要求不是很高的场景;JDK动态代理适用于代理实现了接口的类,对性能要求较高的场景。
CGLIB(Code Generation Library)是一个基于ASM(一个Java字节码操作和分析框架)的代码生成库,它可以在运行时动态生成代理类。相比于JDK动态代理,CGLIB动态代理不要求被代理类实现接口,可以代理任意类。
CGLIB动态代理的原理是通过继承被代理类来创建一个子类作为代理类。在子类中,重写被代理类的方法,并在方法调用前后添加额外的逻辑。CGLIB通过修改字节码的方式实现了这一过程。
下面是使用CGLIB动态代理的代码实现示例:
1. 添加CGLIB依赖:
xml
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
2. 创建被代理类:
public class UserService {
public void addUser() {
System.out.println("添加用户");
}
}
3. 创建代理类:
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import net.sf.cglib.proxy.Enhancer;
public class UserServiceProxy implements MethodInterceptor {
private Object target; // 被代理的对象
public Object getProxyInstance(Object target) {
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("方法调用前");
Object result = method.invoke(target, args);
System.out.println("方法调用后");
return result;
}
}
4. 测试代码:
public class Main {
public static void main(String[] args) {
UserService userService = new UserService();
UserServiceProxy proxy = new UserServiceProxy();
UserService userServiceProxy = (UserService) proxy.getProxyInstance(userService);
userServiceProxy.addUser();
}
}
运行以上代码,输出结果为:
方法调用前
添加用户
方法调用后
通过CGLIB动态代理,我们成功地对UserService类进行了方法拦截和增强。在代理类的intercept方法中,我们可以在方法调用前后添加额外的逻辑,实现了AOP的横切关注点。
JDK(Java Development Kit)动态代理是Java提供的一种动态代理技术,它通过反射机制在运行时动态生成代理类。JDK动态代理要求被代理类实现接口。
JDK动态代理的原理是通过Proxy类和InvocationHandler接口实现的。Proxy类用于创建代理对象,InvocationHandler接口用于定义代理对象的方法调用处理逻辑。
下面是使用JDK动态代理的代码实现示例:
1. 创建被代理接口:
public interface UserService {
void addUser();
}
2. 创建被代理类:
public class UserServiceImpl implements UserService {
@Override
public void addUser() {
System.out.println("添加用户");
}
}
3. 创建代理类:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class UserServiceProxy implements InvocationHandler {
private Object target; // 被代理的对象
public Object getProxyInstance(Object target) {
this.target = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
@Override
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;
}
}
4. 测试代码:
public class Main {
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
UserServiceProxy proxy = new UserServiceProxy();
UserService userServiceProxy = (UserService) proxy.getProxyInstance(userService);
userServiceProxy.addUser();
}
}
运行以上代码,输出结果为:
方法调用前
添加用户
方法调用后
通过JDK动态代理,我们成功地对UserServiceImpl类进行了方法拦截和增强。在代理类的invoke方法中,我们可以在方法调用前后添加额外的逻辑,实现了AOP的横切关注点。
使用Spring AOP实现CGLIB动态代理的代码如下:
1. 首先,需要添加CGLIB的依赖包。在Maven项目中,可以在pom.xml文件中添加以下依赖:
xml
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
2. 创建被代理类:
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
3. 创建切面类:
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
4. 配置Spring AOP:
xml
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
5. 测试代码:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) context.getBean("userService");
userService.addUser();
}
}
运行以上代码,输出结果为:
添加用户
方法调用后
通过Spring AOP结合CGLIB动态代理,我们成功地对UserService类的addUser方法进行了方法拦截和增强。在切面类的logAfter方法中,我们可以在方法调用后添加额外的逻辑,实现了AOP的横切关注点。
使用Spring AOP实现JDK动态代理的代码如下:
1. 创建被代理接口:
public interface UserService {
void addUser();
}
2. 创建被代理类实现该接口:
public class UserServiceImpl implements UserService {
@Override
public void addUser() {
System.out.println("添加用户");
}
}
3. 创建切面类:
public class UserServiceImpl implements UserService {
@Override
public void addUser() {
System.out.println("添加用户");
}
}
4. 配置Spring AOP:
xml
<bean id="userService" class="com.example.UserServiceImpl"/>
<bean id="loggingAspect" class="com.example.LoggingAspect"/>
<aop:config>
<aop:aspect ref="loggingAspect">
<aop:pointcut id="userServicePointcut" expression="execution(* com.example.UserService.addUser(..))"/>
<aop:after pointcut-ref="userServicePointcut" method="logAfter"/>
</aop:aspect>
</aop:config>
5. 测试代码:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) context.getBean("userService");
userService.addUser();
}
}
运行以上代码,输出结果为:
添加用户
方法调用后
通过Spring AOP结合JDK动态代理,我们成功地对UserService接口的addUser方法进行了方法拦截和增强。在切面类的logAfter方法中,我们可以在方法调用后添加额外的逻辑,实现了AOP的横切关注点。