JDK InvocationHandler的动态代理是基于接口来实现的,从newProxyInstance()方法中的参数也可以看出来,假如被代理的对象的类并没有实现接口,而是一个普通的类,那么久可以通过CGLIB动态代理来实现
了解了JDK动态代理之后,再来理解CGLIB相对容易一些,大致流程
1、通过CGLIB的Enhancer对象注入被代理类和方法属性,进而调用create()方法来创建代理对象
2、实现MethodInterceptor接口,重写intercept()方法,可以修改方法实现,功能和JDK动态代理的invoke()方法一样
3、当代理类调用方法时,会转发给MethodInterceptor实现类Override的intercept()方法,最终通过proxy.invokeSuper()方法转发给被代理的对象,完成方法的调用
可以看到,和JDK动态代理思路异曲同工,这里关键可以实现非接口实现类的动态代理
首先新增依赖
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
被代理类,普通类即可
package com.lihuia.cglib;
/**
* Copyright (C), 2018-2019
* FileName: Hello
* Author: lihui
* Date: 2019/11/21
*/
public class Hello {
public String sayHello(String message) {
return "Hello " + message;
}
}
接着必须要实现MethodInterceptor接口,重写intercept,才能接收转发过来的方法,以及通过methodProxy.invokeSuper()转发给被代理类对象执行
package com.lihuia.cglib;
import java.lang.reflect.Method;
import java.util.Arrays;
import lombok.extern.slf4j.Slf4j;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/**
* Copyright (C), 2018-2019
* FileName: HelloInterceptor
* Author: lihui
* Date: 2019/11/21
*/
@Slf4j
public class HelloInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
log.info(Arrays.toString(objects));
return methodProxy.invokeSuper(o, objects);
}
}
最关键的是的注入这里
创建Enhancer类对象,设置SuperClass,以及回调方法
package com.lihuia.cglib;
import net.sf.cglib.proxy.Enhancer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Copyright (C), 2018-2019
* FileName: HelloConfig
* Author: lihui
* Date: 2019/11/21
*/
@Configuration
public class HelloConfig {
@Bean
public HelloInterceptor helloInterceptor() {
return new HelloInterceptor();
}
@Bean
public Enhancer enhancer() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Hello.class);
enhancer.setCallback(helloInterceptor());
return enhancer;
}
}
最后是测试类
package com.lihuia.cglib;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import net.sf.cglib.proxy.Enhancer;
import org.testng.annotations.Test;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
/**
* Copyright (C), 2018-2019
* FileName: HelloTest
* Author: lihui
* Date: 2019/11/21
*/
@ContextConfiguration(classes = {HelloConfig.class})
@Slf4j
public class HelloTest extends AbstractTestNGSpringContextTests {
@Resource
private Enhancer enhancer;
@Test
public void cglibHelloTest() {
Hello proxy = (Hello) enhancer.create();
log.info(proxy.sayHello("World"));
}
}
调用Enhancer的create()方法创建代理类,通过调用方法回调给intercept,最终转发给被代理类的sayHello()方法
OVER