代理是指一个包装了真实访问对象的类,以便控制对真实类的访问
访问流程如下
代码语言:javascript复制public interface SubjectInterface {
void hi();
}
public class RealSubject implements SubjectInterface {
@Override
public void hi() {
System.out.print("hi");
}
}
public class SubjectProxy implements SubjectInterface{
private RealSubject r;
public SubjectProxy() {
r=new RealSubject();
}
@Override
public void hi() {
System.out.println("proxy");
r.hi();
}
}
public class Client {
public static void main(String[] args) {
SubjectInterface subject = new SubjectProxy();
subject.hi();
}
}
此时RealSubject作为代理对象的一个属性字段,在运行之前就会生成RealSubject的字节码文件,这种方式也称作静态代理
动态代理
被代理的类在运行时动态生成的,编译的时候并没有生成RealSubject
使用JDK实现动态代理
jdk实现动态代理必须有实现接口InvocationHandler的处理类,用于执行被代理类的方法
代码语言:javascript复制public class SubjectInvocationHandler implements InvocationHandler {
private Object myproxy;
public SubjectInvocationHandler(Object proxy) {
this.myproxy = proxy;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("invocation handler");
method.invoke(myproxy,args);
return null;
}
}
客户端通过使用java.lang.reflect.Proxy
自行创建代理,然后调用目标方法即可
public class Client {
public static void main(String[] args) {
//classloader会被用来验证是否可以加载传入的接口,
SubjectInterface proxy = (SubjectInterface) Proxy.newProxyInstance(SubjectInterface.class.getClassLoader()
, new Class[]{SubjectInterface.class}
, new SubjectInvocationHandler(new RealSubject()));
proxy.hi();
}
访问流程如下
生成代理proxy class阶段
代理对象会在内部缓存,如果没有缓存则会由ProxyClassFactory
新生成。
首先会做接口校验,比如是否可以从提供的classLoader获取接口
Class<?> interfaceClass = null;
try {
interfaceClass = Class.forName(intf.getName(), false, loader);
} catch (ClassNotFoundException e) {
}
if (interfaceClass != intf) {
throw new IllegalArgumentException(
intf " is not visible from class loader");
}
验证完毕后,会读取接口的class文件使用的是 ProxyGenerator.generateProxyClass
,可以看到它会对整个的class文件的字节做读取
private byte[] generateClassFile() {
...
dout.writeInt(0xCAFEBABE);
...
}
最后调用native方法生成代理对象,并存入缓存
获取proxy的构造函数
构造函数指定的参数就是InvocationHandler
创建实例
调用构造函数,传入自定义的invocationHandler,自此生成了一个proxy实例,且实例本身会实现传入的接口,代码实例生成的对象如下所示
代码语言:javascript复制public final class $Proxy0 extends Proxy implements SubjectInterface {
...
public final void hi() throws {
try {
//这里的h即Proxy中的InvocationHandler,也就是用户自定义的InvocationHanlder
//这个this对象代表的也就是 $Proxy0 本身
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
...
}
从JVM dump下动态代理的类
使用CGlib动态代理
引入CGlib之后,执行如下代码即可
代码语言:javascript复制public class Client {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(RealSubject.class);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("cglib:" method.getName());
methodProxy.invokeSuper(o, objects);
return o;
}
});
RealSubject realSubject = (RealSubject)enhancer.create();
realSubject.hi();
}
}
动态代理在spring aop中的运用
spring中默认使用DefaultAopProxyFactory
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: "
"Either an interface or a target is required for proxy creation.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
//对于接口使用的是JDK
return new JdkDynamicAopProxy(config);
}
//其余使用Cglib作为动态代理的实现
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
JdkDynamicAopProxy
它实现了InvocationHandler和AopProxy。AopProxy主要是负责提供getProxy,实现为
代码语言:javascript复制@Override
public Object getProxy() {
return getProxy(ClassUtils.getDefaultClassLoader());
}
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
当有需要执行的方法的时候,则是执行invoke
代码语言:javascript复制public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
...
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
retVal = invocation.proceed();
...
}
public Object proceed() throws Throwable {
...
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
//这里会执行AfterReturningAdviceInterceptor、AspectJAfterThrowingAdvice等等方法
return dm.interceptor.invoke(this);
}
...
}
CglibAopProxy
它实现了AopProxy,核心的生成代理的方式如下
代码语言:javascript复制public Object getProxy(@Nullable ClassLoader classLoader) {
...
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
enhancer.setSuperclass(proxySuperClass);
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x ) {
types[x] = callbacks[x].getClass();
}
// fixedInterceptorMap only populated at this point, after getCallbacks call above
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
// Generate the proxy class and create a proxy instance.
return createProxyClassAndInstance(enhancer, callbacks);
...
}
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
...
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
...
Callback[] mainCallbacks = new Callback[] {
aopInterceptor, // for normal advice
targetInterceptor, // invoke target without considering advice, if optimized
new SerializableNoOp(), // no override for methods mapped to this
targetDispatcher, this.advisedDispatcher,
new EqualsInterceptor(this.advised),
new HashCodeInterceptor(this.advised)
};
...
else {
callbacks = mainCallbacks;
}
...
}
以DynamicAdvisedInterceptor为例,它就实现了MethodInterceptor
代码语言:javascript复制public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
...
//同样在此处去运行具体的Advice
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
...
}
通常可以使用Proxy的情况
- 虚代理:根据需要创建开销很大的对象,只有用到时才创建
- 保护代理:控制对原始对象的访问
- 智能指引:在访问对象时附加了一些操作,比如对象没有引用时释放它
- 远程代理:为一个对象在不同的地址空间提供局部代表