目录
什么是静态代理
静态代理的实现
- 代理类通过实现与目标对象相同的接口,并在类中维护一个目标对象
- 在代理类中,通过构造器塞入目标对象,赋值给代理对象
- 执行代理对象实现的接口方法,并实现前拦截,后拦截等所需的业务功能
具体的实现查看:https://www.cnblogs.com/cC-Zhou/p/9525638.html
JDK
动态代理是什么
JDK
的动态代理是基于拦截器和反射来实现的。JDK
代理是不需要第三方库支持的,只需要 JDK
环境就可以进行代理
- 必须实现
InvocationHandler
接口 - 使用
Proxy.newProxyInstance
产生代理对象 - 被代理的对象必须要实现接口
JDK 动态代理简单实现
接口
public interface IHello {
void sayHello();
}
接口实现类
public class HelloImpl implements IHello {
@Override
public void sayHello() {
System.out.println("Hello world!");
}
}
实现 InvocationHandler
接口
public class MyInvocationHandler implements InvocationHandler {
/*目标对象*/
private Object target;
public MyInvocationHandler(Object target){
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("------插入前置通知代码-------------");
// 执行相应的目标方法
Object rs = method.invoke(target,args);
System.out.println("------插入后置处理代码-------------");
return rs;
}
}
测试
public class MyProxyTest {
public static void main(String[] args)
throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
IHello iHello2 = (IHello) Proxy.newProxyInstance(IHello.class.getClassLoader(), // 加载接口的类加载器
new Class[]{
IHello.class}, // 一组接口
new MyInvocationHandler(new HelloImpl())); // 自定义的InvocationHandler
iHello2.sayHello();
}
}
结果:
------插入前置通知代码-------------
Hello world!
------插入后置处理代码-------------
JDK
动态代理源码分析
Proxy.newProxyInstance()
方法
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException {
// 如果h为空直接抛出空指针异常,之后所有的单纯的判断null并抛异常,都是此方法
Objects.requireNonNull(h);
// 拷贝类实现的所有接口
final Class<?>[] intfs = interfaces.clone();
// 获取当前系统安全接口
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
// Reflection.getCallerClass 返回调用该方法的方法的调用类;loader:接口的类加载器
// 进行包访问权限、类加载器权限等检查
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
// 查找或生成指定的代理类
Class<?> cl = getProxyClass0(loader, intfs);
// 用指定的调用处理程序调用它的构造函数
try {
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
/**
* 获取代理类的构造函数对象。
* constructorParams是类常量,作为代理类构造函数的参数类型,常量定义如下:
* private static final Class<?>[] constructorParams = { InvocationHandler.class };
*/
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
// 根据代理类的构造函数对象来创建需要返回的代理类对象
return cons.newInstance(new Object[]{
h});
} catch (IllegalAccessException|InstantiationException e) {
throw new InternalError(e.toString(), e);
} catch (InvocationTargetException e) {
Throwable t = e.getCause();
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else {
throw new InternalError(t.toString(), t);
}
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString(), e);
}
}
newProxyInstance()
方法帮我们执行了生成代理类,获取构造器,生成代理对象这三个操作
- 生成代理类ÿ