一、简介
1、定义
指代理类对象在程序运行时由JVM根据反射机制动态生成的,动态代理不需要定义代理类的java源文件
JDK运行期间,动态创建class字节码并加载到JVM
动态代理的实现方式:JDK动态代理,CGLIB动态代理
2、JDK动态代理
基于java的反射机制实现,使用jdk中接口和类实现代理对象的动态创建
jdk的动态要求目标对象必须实现接口
InvocationHandler,Method,Proxy;
- 使用步骤
a.创建接口,定义目标类要完成的功能
b.创建目标类实现接口
c.创建InvocationHandler接口的实现类,在invoke方法中完成代理类的功能:
调用目标方法
功能增强
d.使用proxy类的静态方法,创建代理对象
3、CGLIB动态代理
cglib是第三方的工具库,创建代理对象,cglib的原理是继承,cglib通过继承目标类,创建它的子类,在子类中重写父类中同名的方法,实现功能的修改;
因为cglib继承,重写方法,所以要求目标类不能是final的,方法也不能是final的,cglib的要求目标类比较宽松,只要能继承就可以了,在mybatis和spring AOP中都有使用;且效率高于JDK
二、使用
1、jdk动态代理
@SpringBootTest
public class Test {
@org.junit.jupiter.api.Test
public void testProducer() {
ZhangSan zhangSan = new ZhangSan();
SpeakerProxy speakerProxy = new SpeakerProxy();
speakerProxy.setObject(zhangSan);
Speaker speaker = (Speaker) Proxy.newProxyInstance(zhangSan.getClass().getClassLoader(), new Class[]{Speaker.class},speakerProxy);
speaker.speak();
}
interface Speaker{
public boolean speak();
}
class ZhangSan implements Speaker{
public ZhangSan() {
}
@Override
public boolean speak() {
System.out.println("阐述事实");
return true;
}
}
class SpeakerProxy implements InvocationHandler{
//目标对象
private Object target = null;
public void setObject(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
if(method.getName().equals("speak")){
System.out.println("说话前");
result = method.invoke(target, args);//反射
System.out.println(result);
System.out.println("说话后");
}
return result;
}
}
}
2、cglib动态代理
public interface UserService {
public void save();
}
public class UserServiceImpl implements UserService {
@Override
public void save() {
System.out.println("吃饭");
}
}
public class UserServiceCglibProxy {
public static UserService createUserServiceCglibProxy(Class clazz){
//创建动态的一个字节码对象
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(clazz);
enhancer.setCallback(new MethodInterceptor() {
/**
*
* @param o 被代理出来的类的对象
* @param method 原始方法
* @param args
* @param methodProxy
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object result = methodProxy.invokeSuper(o, args);
if(method.getName().equals("save")){
System.out.println("喝水");
System.out.println("睡觉");
}
return result;
}
});
UserService t = (UserService enhancer.create();
return t;
}
}
class Test{
public static void main(String[] args) {
UserService userService = UserServiceCglibProxy.createUserServiceCglibProxy(UserServiceImpl.class);
userService.save();
}
}