cglib中Enhancer的简单使用

cglib 是一个强大的, 高效高质的代码生成库.

简单的使用方法

Enhancer中有几个常用的方法, setSuperClass和setCallback, 设置好了SuperClass后, 可以使用create制作代理对象了

Enhancer enhancer = new Enhancer();  
enhancer.setSuperclass(EnhancerDemo.class);  

enhancer.setCallback(new MethodInterceptorImpl());  
EnhancerDemo demo = (EnhancerDemo) enhancer.create(); 



实现MethodInterceptor接口

private static class MethodInterceptorImpl implements MethodInterceptor {  


        @Override 
        public Object intercept(Object obj, Method method, Object[] args,  
                MethodProxy proxy) throws Throwable {  
            System.out.println("Before invoke " + method);  
            Object result = proxy.invokeSuper(obj, args);  
            System.out.println("After invoke" + method);  
            return result;  
        }    
    } 

intercept方法, Object result = proxy.invokeSuper(obj, args)调用了原来的方法, 在这个调用前后可以添加其他的逻辑, 相当于AspectJ的around

完整代码如下: 

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 EnhancerDemo {  
    public static void main(String[] args) {  
        Enhancer enhancer = new Enhancer();  
        enhancer.setSuperclass(EnhancerDemo.class);  
        enhancer.setCallback(new MethodInterceptorImpl());  
           
        EnhancerDemo demo = (EnhancerDemo) enhancer.create();  
        demo.test();           
        System.out.println(demo);  
    }  
       
    public void test() {  
        System.out.println("EnhancerDemo test()");  
    }  

   
    private static class MethodInterceptorImpl implements MethodInterceptor {  
        @Override 
        public Object intercept(Object obj, Method method, Object[] args,  
                MethodProxy proxy) throws Throwable {  
            System.err.println("Before invoke " + method);  
            Object result = proxy.invokeSuper(obj, args);  
            System.err.println("After invoke" + method);  
            return result;  
        }            
    }  



运行结果如下:

Before invoke public void EnhancerDemo.test()  
EnhancerDemo test()  
After invokepublic void EnhancerDemo.test()  
Before invoke public java.lang.String java.lang.Object.toString()  
Before invoke public native int java.lang.Object.hashCode()  
After invokepublic native int java.lang.Object.hashCode()  
After invokepublic java.lang.String java.lang.Object.toString()  
EnhancerDemo$$EnhancerByCGLIB$$bc9b2066@1621e42 

我们可以看到System.out.println(demo), demo首先调用了toString()方法, 然后又调用了hashCode,  
生成的对象为EnhancerDemo$$EnhancerByCGLIB$$bc9b2066的实例, 这个类是运行时由cglib产生的

使用CGLIB代理计算方法耗时的步骤如下: 1. 引入cglib和asm的依赖。 2. 创建一个实现MethodInterceptor接口的拦截器类,重写intercept方法,在方法前后记录时间。 3. 在Controller定义一个需要计算耗时的方法,并在方法前加上@LogTime注解。 4. 使用AspectJ切面编程,在@Before获取目标方法并判断是否有@LogTime注解,如果有则使用CGLIB代理该方法并调用,实现计算方法耗时的功能。 示例代码如下: 1. 引入依赖 ``` <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.3.0</version> </dependency> <dependency> <groupId>org.ow2.asm</groupId> <artifactId>asm</artifactId> <version>7.1</version> </dependency> ``` 2. 编写拦截器 ``` public class TimeInterceptor implements MethodInterceptor { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { long startTime = System.currentTimeMillis(); Object result = proxy.invokeSuper(obj, args); long endTime = System.currentTimeMillis(); System.out.println(method.getName() + " cost " + (endTime - startTime) + " ms"); return result; } } ``` 3. 定义需要计算耗时的方法 ``` @RestController public class TestController { @LogTime @GetMapping("/test") public String test() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } return "test"; } } ``` 4. 编写切面 ``` @Aspect @Component public class TimeAspect { @Autowired private ApplicationContext context; @Pointcut("@annotation(com.example.demo.annotation.LogTime)") public void logTime() { } @Before("logTime()") public void beforeLogTime(JoinPoint joinPoint) throws Throwable { Object target = joinPoint.getTarget(); MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); if (method.isAnnotationPresent(LogTime.class)) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(target.getClass()); enhancer.setCallback(new TimeInterceptor()); Object proxy = enhancer.create(); Method proxyMethod = proxy.getClass().getMethod(method.getName(), method.getParameterTypes()); proxyMethod.invoke(proxy, joinPoint.getArgs()); } } } ``` 5. 测试 启动Spring Boot应用,并访问http://localhost:8080/test,可以看到控制台输出以下信息: ``` test cost 1000 ms ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值