Fork me on GitHub

Spring源码阅读之AOP两种代理模式

AOP

github简易Spring实现

一般用作:日志,权限控制,异常,事务等情况下。

xml中的解析

1
2
3
4
5
6
7
8
<bean id="autoProxyCreator" class="us.codecraft.tinyioc.aop.AspectJAwareAdvisorAutoProxyCreator"></bean>

<bean id="timeInterceptor" class="us.codecraft.tinyioc.aop.TimerInterceptor"></bean>

<bean id="aspectjAspect" class="us.codecraft.tinyioc.aop.AspectJExpressionPointcutAdvisor">
<property name="advice" ref="timeInterceptor"></property>
<property name="expression" value="execution(* us.codecraft.tinyioc.*.*(..))"></property>
</bean>

AspectJAwareAdvisorAutoProxyCreator implements BeanPostProcessor
所以扫描这个类的时候会执行AspectJAwareAdvisorAutoProxyCreator.postProcessAfterInitialization()。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public Object postProcessAfterInitialization(Object bean, String beanName) throws Exception {
if (bean instanceof AspectJExpressionPointcutAdvisor) {
return bean;
}
if (bean instanceof MethodInterceptor) {
return bean;
}
List<AspectJExpressionPointcutAdvisor> advisors = beanFactory
.getBeansForType(AspectJExpressionPointcutAdvisor.class);
for (AspectJExpressionPointcutAdvisor advisor : advisors) {
if (advisor.getPointcut().getClassFilter().matches(bean.getClass())) {
ProxyFactory advisedSupport = new ProxyFactory();
advisedSupport.setMethodInterceptor((MethodInterceptor) advisor.getAdvice());
advisedSupport.setMethodMatcher(advisor.getPointcut().getMethodMatcher());

TargetSource targetSource = new TargetSource(bean, bean.getClass(), bean.getClass().getInterfaces());
advisedSupport.setTargetSource(targetSource);

return advisedSupport.getProxy();
}
}
return bean;
}

然后遍历所有的AspectJExpressionPointcutAdvisor,如果有其他的bean满足条件advisor.getPointcut().getClassFilter().matches(bean.getClass())那么则返回代理对象。

这里面的返回代理对象如果用代码来写的话就是下面这样,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
   // 1. 设置被代理对象(Joinpoint)
AdvisedSupport advisedSupport = new AdvisedSupport();
TargetSource targetSource = new TargetSource(helloWorldService, HelloWorldServiceImpl.class,
HelloWorldService.class);
advisedSupport.setTargetSource(targetSource);

//设置匹配的match
MethodMatcher methodMatcher = new MethodMatcher() {

@Override
public boolean matches(Method method, Class targetClass) {
return true;
}
};
advisedSupport.setMethodMatcher(methodMatcher);

// 2. 设置拦截器(Advice)
TimerInterceptor timerInterceptor = new TimerInterceptor();
advisedSupport.setMethodInterceptor(timerInterceptor);

// 3. 创建代理(Proxy)
JdkDynamicAopProxy jdkDynamicAopProxy = new JdkDynamicAopProxy(advisedSupport);
HelloWorldService helloWorldServiceProxy = (HelloWorldService) jdkDynamicAopProxy.getProxy();

// 4. 基于AOP的调用
helloWorldServiceProxy.helloWorld();

advisedSupport{targetSource,methodMatcher,methodInterceptor}
这个里面记录了代理目标,和匹配的expression和具体的拦截操作

JDK动态代理

implements InvocationHandler

先获取代理类Proxy.newProxyInstance(getClass().getClassLoader(), advised.getTargetSource().getInterfaces(), this);,然后implements InvocationHandler ,上面的this,执行target方法的时候就会优先执行InvocationHandler.invoke(final Object proxy, final Method method, final Object[] args);

Proxy.newProxyInstance()

这个是jdk动态代理,需要代理类实现接口,而且只能代理接口里面的方法,因为使用接口来创建代理。

Proxy.newProxyInstance(),获取代理类方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
Objects.requireNonNull(h);//InvocationHandler 不为空

final Class<?>[] intfs = interfaces.clone();

/*
* Look up or generate the designated proxy class.
* 查找或生成指定的代理类。
*/
Class<?> cl = getProxyClass0(loader, intfs);//

/*
* Invoke its constructor with the designated invocation handler.
* 用指定的调用处理程序调用它的构造函数。 constructorParams = InvocationHandler.class
*/
final Constructor<?> cons = cl.getConstructor(constructorParams);

return cons.newInstance(new Object[]{h});//返回代理类

}

getProxyClass0()

1
2
3
4
5
6
7
8
9
10
11
12
13
private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) {
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}

// If the proxy class defined by the given loader implementing
// the given interfaces exists, this will simply return the cached copy;
// otherwise, it will create the proxy class via the ProxyClassFactory
//如果classloader加载的接口代理类存在,直接从cache中国返回
//否则从ProxyClassFactory创建一个新的代理类
return proxyClassCache.get(loader, interfaces);
}

CGLIB

implements MethodInterceptor

获取代理类

Enhancer e=new Enhancer();//创建代理对象类
e.setSuperclass(object.getClass());//声明代理对象的父类是谁(是目标对象)
e.setCallback(this);//设置回调函数,即调用intercept()
return e.create();//返回创建的代理对象

执行intercept(Object obj, Method method, Object[] args, MethodProxy proxy);

文章目录
  1. 1. JDK动态代理
    1. 1.1. Proxy.newProxyInstance()
  2. 2. CGLIB
,