jdk动态代理
jdk动态代理采用字节重组,重新生成代理对象来替代原始对象,以达到动态代理的目的。
jdk动态代理的原理步骤如下:
- 获取被代理对象的引用。
- jdk动态代理类重新生成一个新的类,新的类需要实现被代理实现的所有接口。
- 动态生成java代码,新的类的方法调用父类java.lang.reflect.Proxy的java.lang.reflect.InvocationHandler属性的java.lang.reflect.InvocationHandler#invoke方法。从而进入到增强方法中。
- 编译java文件为class文件。
- 将代理类加载到jvm中。
jdk动态代理代码实现
抽象主题角色接口
package com.ludk.proxy;
public interface IUserService {
void select();
}
真实主题角色类
package com.ludk.proxy;
public class UserServiceImpl implements IUserService {
@Override
public void select() {
System.out.println("真实主题角色实现");
}
}
增强主题角色类
package com.ludk.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class ProxyHandler implements InvocationHandler {
// 用于存储真实的被代理对象
Object target;
public ProxyHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object result=method.invoke(target,args);
after();
return null;
}
private void before(){
System.out.println("执行方法前:");
}
private void after(){
System.out.println("执行方法后:");
}
}
测试类
package com.ludk.proxy;
import java.lang.reflect.Proxy;
public class ProxyTest {
public static void main(String[] args) {
IUserService iUserService=new UserServiceImpl();
ProxyHandler handler=new ProxyHandler(iUserService);
IUserService userService=(IUserService) Proxy.newProxyInstance(iUserService.getClass().getClassLoader(),iUserService.getClass().getInterfaces(),handler);
userService.select();
}
}
测试结果
执行方法前:
真实主题角色实现
执行方法后:
cglib动态代理
是基于继承实现的动态代理
cglib动态代理代码实现
被代理对象
package com.ludk.proxy.cglibproxy;
public class UserService {
public void select(){
System.out.println("select 方法代码逻辑");
}
}
代理对象的增强类
package com.ludk.proxy.cglibproxy;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class ProxyInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
before();
Object result=methodProxy.invokeSuper(o,objects);
after();
return result;
}
private void before(){
System.out.println("方法执行前:");
}
private void after(){
System.out.println("方法执行后:");
}
}
测试类
package com.ludk.proxy.cglibproxy;
import org.springframework.cglib.proxy.Enhancer;
public class CglibProxyTest {
public static void main(String[] args) {
// Enhancer 为 CGLIB 代理增强类
Enhancer enhancer=new Enhancer();
// 设置被代理类(父类),以便 CGLIB 去生成该类的子类
enhancer.setSuperclass(UserService.class);
// 你可以认为是设置增强方法
enhancer.setCallback(new ProxyInterceptor());
// 生成代理对象
UserService proxy = (UserService) enhancer.create();
// 执行代理方法
proxy.select();
System.out.println();
}
}
测试结果
方法执行前:
select 方法代码逻辑
方法执行后:
jdk动态代理与cglib动态代理对比
jdk动态代理被代理类必须实现接口,因为是通过生成接口实现类实现的。
cglib动态代理被代理类不能被final修饰,方法不能private,因为是基于被代理类的子类通过字节码增强技术实现的。被代理类不能被final修饰、方法被private修饰时,子类不能重写父类方法。