由《Spring的IOC的源码解析(三)》继续分析!
首先介绍一下容器命名空间句柄 ContextNamespaceHandler
位置:spring-context-*.jar的META-INF/spring-handlers
容器命名空间句柄:
http\:// www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler
ContextNamespaceHandler的init方法实现如下,
registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());
registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());
registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());
当
ContextNamespaceHandler在解析标签的时候,会调用每种标签的解析器,解析过程就会调用
AopNamespaceUtils为当前类型的标签
尝试
注册相应的BPP;下边给出一些示例,格式为:
{标签-标签解析器-注册的BPP}
config/
ConfigBeanDefinitionParser/
AspectJAwareAdvisorAutoProxyCreator
aspectj-autoproxy/
AspectJAutoProxyBeanDefinitionParser/
AnnotationAwareAspectJAutoProxyCreator
load-time-weaver/
LoadTimeWeaverBeanDefinitionParser/没有
component-scan/
ComponentScanBeanDefinitionParser/没有
继续分析AOP Proxy对象的生成过程!
(1)获取能够处理目标类的advisor
首先是调用AbstractAdvisorAutoProxyCreator.
getAdvicesAndAdvisorsForBean()方法,然后调用:
protected List findEligibleAdvisors(Class> beanClass, String beanName) {
List candidateAdvisors = findCandidateAdvisors();
//这个方法就是去beanFactory中查询全部Advisor类型的bean,然后初始化;参见(a)
List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);//参看(b)
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);//排序
}
return eligibleAdvisors;
(a) 获取并初始化Advisor,实现逻辑在
BeanFactoryAdvisorRetrievalHelper.findAdvisorBeans(),其核心代码是:
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Advisor.class, true, false);
//查询所有注册在工厂中的Advisor的bean name or id
List advisors = new LinkedList<>();
advisors.add(this.beanFactory.getBean(name, Advisor.class));
//初始化Advisor,同时也会初始化Advisor中的advice,生成一个advice实例;
(b) 往后又调用
AopUtils.findAdvisorsThatCanApply()方法;
findAdvisorsThatCanApply调用的核心函数就是:
public static boolean canApply(Advisor advisor, Class> targetClass, boolean hasIntroductions) {
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
//advisor是
IntroductionAdvisor的匹配过程
}
else if (advisor instanceof PointcutAdvisor) {//正常使用AOP,都是这种advisor
PointcutAdvisor pca = (PointcutAdvisor) advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
//advisor是
PointcutAdvisor的匹配过程
}
else {
// It doesn't have a pointcut so we assume it applies.
return true;
//其他的
advisor
默认要处理
}
pointcut的匹配过程如下:
public static boolean canApply(Pointcut pc, Class> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
if (!pc.getClassFilter().matches(targetClass)) {
//获取advisor中的pointcut对象,关于pointcut的使用,请参看《
spring中的pointcut
》;这里相当于把所有的advisor中的pointcut都拿来匹配一遍,看看是否满足
return false;
}
MethodMatcher methodMatcher = pc.getMethodMatcher();
if (methodMatcher == MethodMatcher.TRUE) {
// No need to iterate the methods if we're matching any method anyway...
return true;
}
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
Set> classes = new LinkedHashSet<>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
classes.add(targetClass);
for (Class> clazz : classes) {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
if ((introductionAwareMethodMatcher != null &&
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
最终,返回所有适合代理类的advisor
(2)创建AOP代理
protected Object createProxy(Class> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
//
为bean设置属性org.springframework.aop.framework.autoproxy.AutoProxyUtils.originalTargetClass,值是beanClass
}
ProxyFactory proxyFactory = new ProxyFactory();
//代理工厂
proxyFactory.copyFrom(this);
//为代理工厂设置proxyTargetClass,是否初始化等参数
if (!proxyFactory.isProxyTargetClass()) {
//默认应该条件为true,进入if
if (shouldProxyTargetClass(beanClass, beanName)) {
//判断是代理类,还是代理类的接口;判断的逻辑就是看bean的定义中,属性名为
org.springframework.aop.framework.autoproxy.AutoProxyUtils.preserveTargetClass的属性的值是否设置为了true。暂时只知道
ConfigurationClassPostProcessor可以配置这个属性为true;默认是false,即代理接口
proxyFactory.setProxyTargetClass(true);
//代理目标类,标记
proxyTargetClass=true
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
//代理目标类的接口;如果是可以代理的接口,就把接口加入到ProxyFactory中,见(a)
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
//合并共用和指定拦截器到advisor,可以把advisor叫做增强器;见(b)
proxyFactory.addAdvisors(advisors);
//这是增强器
proxyFactory.setTargetSource(targetSource);//设置实例对象,用于代理调用代理方法是使用
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(getProxyClassLoader());
//生成代理对象,见(c)
(a)
可代理的接口的定义
至少有一个方法的接口
或者
protected boolean isInternalLanguageInterface(Class> ifc) {
return (ifc.getName().equals("groovy.lang.GroovyObject") ||
ifc.getName().endsWith(".cglib.proxy.Factory") ||
ifc.getName().endsWith(".bytebuddy.MockAccess"));
}
protected boolean isConfigurationCallbackInterface(Class> ifc) {
return (InitializingBean.class == ifc || DisposableBean.class == ifc || Closeable.class == ifc ||
AutoCloseable.class == ifc || ObjectUtils.containsElement(ifc.getInterfaces(), Aware.class));
返回false的接口
(b)合并共用和指定拦截器到advisor,默认没有共用拦截器
protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
Advisor[] commonInterceptors = resolveInterceptorNames();
//把定义的拦截器包装成advisor,返回
List allInterceptors = new ArrayList<>();
if (specificInterceptors != null) {
allInterceptors.addAll(Arrays.asList(specificInterceptors));
if (commonInterceptors.length > 0) {
if (this.applyCommonInterceptorsFirst) {
//默认把拦截器的执行放在最前边执行
allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
}
else {
allInterceptors.addAll(Arrays.asList(commonInterceptors));
}
}
}
Advisor[] advisors = new Advisor[allInterceptors.size()];
for (int i = 0; i < allInterceptors.size(); i++) {
advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
//包装advisor,适配方法是
DefaultAdvisorAdapterRegistry.wrap()
}
return advisors;
适配过程:
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
if (adviceObject instanceof Advisor) {
return (Advisor) adviceObject;
//如果是advisor对象,不用处理
}
if (!(adviceObject instanceof Advice)) {
//只能是advicor or advice
throw new UnknownAdviceTypeException(adviceObject);
}
Advice advice = (Advice) adviceObject;
//advice对象都包装成
DefaultPointcutAdvisor对象
if (advice instanceof MethodInterceptor) {
// So well-known it doesn't even need an adapter.
return new DefaultPointcutAdvisor(advice);
}
for (AdvisorAdapter adapter : this.adapters) {
// Check that it is supported.
if (adapter.supportsAdvice(advice)) {
return new DefaultPointcutAdvisor(advice);
}
}
throw new UnknownAdviceTypeException(advice);
(c)代理工厂生成代理对象
这里一直没有读懂aopProxyFactory对象的实例话,这里假定aopProxyFactory就是一个DefaultAopProxyFactory对象;
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)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
//类代理,分析过程见【1】
}
else {
return new JdkDynamicAopProxy(config);
//接口代理,
分析过程见
【2】
}
如果不是代理接口,就使用CGLIB字节码动态代理;否则使用JDK的动态代理。
【1】
jdk动态代理
JdkDynamicAopProxy.getProxy()方法:
public Object getProxy(@Nullable ClassLoader classLoader) {
Class>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised
, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
所以,返回的代理对象就是JDK的Proxy.newProxyInstance方法生成的,而且参数需要的
InvocationHandler对象就是当前的JdkDynamicAopProxy对象;
我们知道,JDK动态代理的实现原理就是代理对象在执行目标方法的时候,会检查当前方法是否被代理?如果被代理,那么就执行
InvocationHandler的invoke方法代替;
下边看看JDK动态代理模式下的,代理对象真正执行方法时,切面织入方法的功能是怎样实现的。
JdkDynamicAopProxy实现
InvocationHandler接口,invoke方法的核心逻辑是:
List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
//
chain是
InterceptorAndDynamicMethodMatcher链表;
参见{1}
if (chain.isEmpty()) {
//跳过热交换,只是执行目标类的方法,method.invoke
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
//创建 method invocation
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
//反射方法处理过程,target参数就是被代理类的实例
//执行拦截器链和方法,参看{4}
retVal = invocation.proceed();
}
{1}把增强器advisors包装成mathodMatcher链的过程
调用DefaultAdvisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice()方法,
核心代码如下:
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
//
registry是
DefaultAdvisorAdapterRegistry实例,这里就是把advisor中的advice包装成
MethodInterceptor,见{2}
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
//获得匹配方法;参见{3}
if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
if (mm.isRuntime()) {
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
//采用组合模式,将拦截器对象和匹配方法对象放在
InterceptorAndDynamicMethodMatcher对象中,得到返回值对象;
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
{2}例如:下边是默认包装关系
MethodBeforeAdvice MethodBeforeAdviceInterceptor
AfterReturningAdvice AfterReturningAdviceInterceptor
ThrowsAdvice ThrowsAdviceInterceptor
根据advice的解析过程可知,before 类型的advice的目标类就是MethodBeforeAdvice类的子类;advice的pointcut依赖指定的目标类是AspectJExpressionPointcut
{3}由{2}的说明可知,MethodMatcher方法对象的获取过程就是获取AspectJExpressionPointcut对象;在pointcut实例化时会解析expression表达式,逻辑如下:
private PointcutExpression buildPointcutExpression(@Nullable ClassLoader classLoader) {
PointcutParser parser = initializePointcutParser(classLoader);
PointcutParameter[] pointcutParameters = new PointcutParameter[this.pointcutParameterNames.length];
for (int i = 0; i < pointcutParameters.length; i++) {
pointcutParameters[i] = parser.createPointcutParameter(
this.pointcutParameterNames[i], this.pointcutParameterTypes[i]);
}
return parser.parsePointcutExpression(replaceBooleanOperators(resolveExpression()),
this.pointcutDeclarationScope, pointcutParameters);
//expression的对象类是
PointcutExpressionImpl
需要说明的是,AspectJExpressionPointcut类实现IntroductionAwareMethodMatcher、MethodMatcher接口;
{4}循环处理拦截器链,使用matcher匹配,然后调用拦截器的invoke方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
//所有 advice都调用完之后,调用这里,但是after advice是逆向调用的,所有代理方法会在after adviec之前之前执行
return invokeJoinpoint();
//other code
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
//匹配;见{5}分析
return dm.interceptor.invoke(this);
//调用;参见{6}
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
//如果匹配失败,跳过当前advisor,继续下一个
{5}可知匹配过程就是AspectJExpressionPointcut的matches方法逻辑过程;
{6}看看典型advice的处理过程
before advice的
MethodBeforeAdviceInterceptor调用过程如下:
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
//
AspectJMethodBeforeAdvice.before方法,这里就是调用before通知在切面里定义的执行方法
return mi.proceed();
//跳转到
ReflectiveMethodInvocation.
proceed()方法,实现调用多个advice的功能
AspectJMethodBeforeAdvice.before(){
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
after-returning的AfterReturningAdviceInterceptor调用过程如下:
public Object invoke(MethodInvocation mi) throws Throwable {
Object retVal = mi.proceed();
//跳转到
ReflectiveMethodInvocation.
proceed()方法,实现调用多个advice的功能
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
//调用后处理方法
return retVal;
AspectJAfterReturningAdvice.afterReturning(){
if (shouldInvokeOnReturnValueOf(method, returnValue)) {
invokeAdviceMethod(getJoinPointMatch(), returnValue, null);
}
可见,所有的advice都是先执行before advice 再执行after-returning advice ;所有的advice都执行完之后,执行被代理的方法;因为after advice是逆向调用的,所以被代理的方法会在after advice之前调用。
around advice通知是怎么实现的呢?
看到DefaultAdvisorAdapterRegistry类的wrap方法:
if (adviceObject instanceof Advisor) {
//advice 不是advisor,跳过
return (Advisor) adviceObject;
}
if (!(adviceObject instanceof Advice)) {
throw new UnknownAdviceTypeException(adviceObject);
}
Advice advice = (Advice) adviceObject;
if (advice instanceof MethodInterceptor) {
// So well-known it doesn't even need an adapter.
return new DefaultPointcutAdvisor(advice);
//advice 都在这里处理,被适配成
DefaultPointcutAdvisor对象
再看拦截器方法链——也就是advice的方法封装,也是DefaultAdvisorAdapterRegistry的方法:
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List interceptors = new ArrayList<>(3);
Advice advice = advisor.getAdvice();
if (advice instanceof MethodInterceptor) {
//around advice的处理类
AspectJAroundAdvice实现了
MethodInterceptor接口,所以就是around advice的方法拦截器就是
AspectJAroundAdvice对象
interceptors.add((MethodInterceptor) advice);
}
for (AdvisorAdapter adapter : this.adapters) {
if (adapter.supportsAdvice(advice)) {
interceptors.add(adapter.getInterceptor(advisor));
}
}
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
}
return interceptors.toArray(new MethodInterceptor[interceptors.size()]);
下边看方法拦截器的调用过程:
public Object invoke(MethodInvocation mi) throws Throwable {
if (!(mi instanceof ProxyMethodInvocation)) {
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
}
ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
//返回一个
MethodInvocationProceedingJoinPoint对象,这个对象就是在切面中定义的around方法的实参
JoinPointMatch jpm = getJoinPointMatch(pmi);
return invokeAdviceMethod(pjp, jpm, null, null);
//调用父类的方法;参见{7}
{7}advice方法的调用,核心就是下边这一句
this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
解释:
this.aspectJAdviceMethod获取advice指定方法的Method对象;
this.aspectInstanceFactory.getAspectInstance()获取一个advice所属切面aspect的实例;
也就是method.invoke(object,args)而已;
before advice,after-returning advice在调用advice方法时,会调用下一个advice的方法,但是around advice没有这样做;事实上,around advice调用下一个advice方法的语句在,切面实现的方法中,从这一点上将,只有around advice的方法参数是必须要被使用的;而在around advice方法中,可以在point.proceed();语句前后加增强语句,正是“环绕”的意义所在;需要注意的是,如果有多个around advice被执行,那么point.proceed();语句后面的增强语句的执行过程像堆栈调用,即先被调用的后被执行;
到此,基于JDK的动态代理实现的AOP过程就分析完成了!
【2】
字节码代理
ObjenesisCglibAopProxy.
getProxy()方法,暂时不研究了!