代理是指一個包裝了真實訪問對象的類,以便控制對真實類的訪問java
訪問流程以下spring
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的字節碼文件,這種方式也稱做靜態代理segmentfault
被代理的類在運行時動態生成的,編譯的時候並無生成RealSubject緩存
jdk實現動態代理必須有實現接口InvocationHandler的處理類,用於執行被代理類的方法bash
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
自行建立代理,而後調用目標方法便可app
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();
}
複製代碼
訪問流程以下ide
代理對象會在內部緩存,若是沒有緩存則會由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文件的字節作讀取ui
private byte[] generateClassFile() {
...
dout.writeInt(0xCAFEBABE);
...
}
複製代碼
最後調用native方法生成代理對象,並存入緩存this
構造函數指定的參數就是InvocationHandler
調用構造函數,傳入自定義的invocationHandler,自今生成了一個proxy實例,且實例自己會實現傳入的接口,代碼實例生成的對象以下所示
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);
}
}
...
}
複製代碼
引入CGlib以後,執行以下代碼便可
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中默認使用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);
}
}
複製代碼
它實現了InvocationHandler和AopProxy。AopProxy主要是負責提供getProxy,實現爲
@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
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);
}
...
}
複製代碼
它實現了AopProxy,核心的生成代理的方式以下
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
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();
...
}
複製代碼