Java-CGLib动态代理

导读

Spring-AOP基础知识

Java-JDK动态代理

Java-CGLib动态代理


问题

另一篇博文中的问题

性能监视横切逻辑代码


CGLib动态代理和JDK动态代理的区别

我们知道使用JDK创建代理时只能为接口创建代理实例。我们从Proxy的newProxyInstance方法中可以看出

    @CallerSensitive
    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)

第二个参数interfaces就是需要代理实例实现的接口列表。

对于没有通用接口定义业务方法的类,该如何动态创建代理实例呢?
JDK动态代理技术显然无能为力了,CGLib作为一个替代者,很好地解决了这个问题


CGLib概述

CGLib采用底层的字节码技术,可以为一个类创建子类,在子类中采用方法拦截的技术拦截所有父类方法的调用并顺势织入横切逻辑。


改造

代码已托管到Github—> https://github.com/yangshangwei/SpringMaster

首先在我们的java maven工程中 添加依赖

	<!-- https://mvnrepository.com/artifact/cglib/cglib -->
		<dependency>
			<groupId>cglib</groupId>
			<artifactId>cglib</artifactId>
			<version>${cglib.version}</version>
		</dependency>

使用的版本为 3.2.5

这里写图片描述

package com.xgj.aop.base.cglib;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

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 obj, Method method, Object[] args,
			MethodProxy proxy) throws Throwable {
		// 横切逻辑代码
		PerformanceMonitor.begin(obj.getClass().getName() + "."
				+ method.getName());
		// 业务逻辑,通过代理类调用父类中的方法
		Object result = proxy.invokeSuper(obj, args);
		// 横切逻辑代码
		PerformanceMonitor.end();
		return result;
	}

}

上述代码,我们通过getProxy(Class clazz)方法为一个类创建动态代理对象,该代理对象通过扩展clazz实现代理。

在这个代理对象中,织入性能监视的横切逻辑。

public Object intercept(Object obj, Method method, Object[] args,MethodProxy proxy) 是CGLib定义的Interceptor接口方法,它拦截所有目标类方法中的调用。

其中

  • obj表述目标类的实例

  • method为目标类方法的反射对象

  • args为方法的动态入参

  • proxy为代理类的实例

测试类

通过CglibProxy为ForumSerivceImpl类创建代理对象,并测试代理对象的方法

package com.xgj.aop.base.cglib;

public class ForumServiceTest {

	public static void main(String[] args) {

		CglibProxy cglibProxy = new CglibProxy();
		// 通过动态生成子类的方式创建代理类
		ForumServiceImpl forumService = (ForumServiceImpl) cglibProxy
				.getProxy(ForumServiceImpl.class);
		// 调用代理类的业务方法
		forumService.removeTopic(1);
		forumService.removeForum(2);
	}
}

运行结果

这里写图片描述

通过输出,可以看到除了两个业务方法中都织入了性能监控的逻辑外,还发现代理类的名字变成了

com.xgj.aop.base.cglib.ForumServiceImpl$$EnhancerByCGLIB$$2088954a

这个特殊的类就是CGLib为ForumServiceImpl动态创建的子类。

注意:由于cglib采用动态创建子类的方式生成代理对象,所以不能对目标类中的final或者private方法进行代理

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
下面是一个使用CGLIB进行动态代理的简单例子: 假设我们有一个接口UserService,其中定义了一个方法getUserById(int id),我们希望对该方法进行拦截,记录方法的执行时间。我们可以使用CGLIB来生成,并通过MethodInterceptor来实现拦截逻辑。 首先,我们需要引入CGLIB的相关依赖: ```xml <!-- CGLIB --> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.3.0</version> </dependency> ``` 然后,定义一个UserService的实现UserServiceImpl: ```java public class UserServiceImpl implements UserService { @Override public User getUserById(int id) { // 模拟查询数据库 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } return new User(id, "张三"); } } ``` 接下来,我们定义一个MethodInterceptor来实现拦截逻辑: ```java public class TimeInterceptor implements MethodInterceptor { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { long start = System.currentTimeMillis(); Object result = proxy.invokeSuper(obj, args); long end = System.currentTimeMillis(); System.out.println("方法" + method.getName() + "执行时间:" + (end - start) + "ms"); return result; } } ``` 最后,我们使用CGLIB生成,将拦截逻辑加入到中: ```java public class CglibTest { public static void main(String[] args) { UserServiceImpl userService = new UserServiceImpl(); Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(userService.getClass()); enhancer.setCallback(new TimeInterceptor()); UserService proxy = (UserService) enhancer.create(); proxy.getUserById(1); } } ``` 在上面的码中,我们使用Enhancer来生成,将原始的UserService实现作为的父,然后设置MethodInterceptor作为的回调函数。最后,我们通过enhancer.create()方法来创建,并将其强制转换为UserService接口型,从而实现的功能。 当我们调用的getUserById方法时,MethodInterceptor中的intercept方法将被执行,从而实现了对方法的拦截。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小小工匠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值