Spring内部方法调用代理为什么不生效

前言

先来看以下的代码

@Service
public class CacheService {

    public String noCache() {
        return cache();
    }

    @Cacheable(value = "test")
    public String cache() {
        System.out.println("cache");
        return "222";
    }
}

如下使用方式

@Controller
public class CacheController {

    @Autowired
    CacheService cacheService;

    @RequestMapping(value = "/cache")
    @ResponseBody
    public String cache() {
        return cacheService.cache();
    }

    @RequestMapping(value = "/no-cache")
    @ResponseBody
    public String noCache() {
        return cacheService.noCache();
    }
}

那开启@EnableCaching时,访问 /cache 一次之后,就不会再打印出cache的日志,而调用 /no-cache则每次都会输出,为什么都是通过 CacheService,最终都是调用 CacheService.cache方法,输出不一样呢?

分析

当Spring容器启动时,对于扫描到的Bean,在初始化Bean时,都会调用 BeanPostProcessor

public interface BeanPostProcessor {
    
    /**
     * 在Bean初始化之前调用
     */
	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}
    /**
     * 在Bean初始化之后调用
     */
	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

}

在启用Aop时,默认会注册 InfrastructureAdvisorAutoProxyCreator bean, 而这个bean也实现了接口 BeanPostProcessor, 当Spring 扫描了所以的Bean后,会进行相应Bean的初始化,在Spring中,对于所有的Bean 会进行代理封装,来看下 InfrastructureAdvisorAutoProxyCreator的实现

	@Override
	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (!this.earlyProxyReferences.contains(cacheKey)) {
                // 进行封装
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}
	protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        // 如果已经处理过了,直接返回
		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
        // 如果是增强bean,直接返回
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
        
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}
        // 如果有配置增器,如 @Cachable,需要进行aop拦截的类时,会进行代理处理
		// Create proxy if we have advice.
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		if (specificInterceptors != DO_NOT_PROXY) {
			this.advisedBeans.put(cacheKey, Boolean.TRUE);
            // 创建代理,传入 bean的类型,bean的名称,方法的拦截器,TargetSource(这里SingletonTargetSource)
            // targetSource包含了当前代理的实际bean
			Object proxy = createProxy(
					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}

这里传入createProxy 里的TargetSource是 SingletonTargetSource,这也为代理扩展提供了可能,如PrototypeTargetSource 原型的TargetSource,ThreadLocalTargetSource。

接着再看 createProxy

	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);
		}

		ProxyFactory proxyFactory = new ProxyFactory();
		proxyFactory.copyFrom(this);

		if (!proxyFactory.isProxyTargetClass()) {
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}
        // 这里会调用到 ProxyFacory
		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		proxyFactory.addAdvisors(advisors);
        // 传入当前的bean的信息
		proxyFactory.setTargetSource(targetSource);
		customizeProxyFactory(proxyFactory);

		proxyFactory.setFrozen(this.freezeProxy);
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}

		return proxyFactory.getProxy(getProxyClassLoader());
	}

这里会通过 ProxyFacotry -> AopProxy -> CglibAopProxy

最终会进行拦截的对象的代理注册

        	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的内容,这里是最终代理的MethodInterceptor
			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);

而这里的最终会使用 DynamicAdvisedInterceptor 进行处理 Bean的方法调用

private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {

		private final AdvisedSupport advised;
        //advised 是代理的配置信息,包括了 targetSource
		public DynamicAdvisedInterceptor(AdvisedSupport advised) {
			this.advised = advised;
		}

		@Override
		@Nullable
		public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
			Object oldProxy = null;
			boolean setProxyContext = false;
			Object target = null;
            // 获取当前代理的目标对象
			TargetSource targetSource = this.advised.getTargetSource();
			try {
				if (this.advised.exposeProxy) {
					// Make invocation available if necessary.
					oldProxy = AopContext.setCurrentProxy(proxy);
					setProxyContext = true;
				}
				// 获取代理的bean实际对象
				target = targetSource.getTarget();
				Class<?> targetClass = (target != null ? target.getClass() : null);
                // 获取当前需要进行增强的逻辑,如CacheInterceptor
                // 而这里的所有拦截器,都可以通过 Advisor进行注册
				List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
				Object retVal;
                // 如果未找到拦截列表,直接调用方法
				if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
					Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
					retVal = methodProxy.invoke(target, argsToUse);
				}
				else {
				    // 将原始的bean传入CglibMethodInvocation进行调用
					retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
				}
				retVal = processReturnType(proxy, target, method, retVal);
				return retVal;
			}
			finally {
				if (target != null && !targetSource.isStatic()) {
					targetSource.releaseTarget(target);
				}
				if (setProxyContext) {
					// Restore old proxy.
					AopContext.setCurrentProxy(oldProxy);
				}
			}
		}
}

CglibMethodInvocation 继承 ReflectiveMethodInvocation

	public Object proceed() throws Throwable {
		// this.currentInterceptorIndex 默认是-1 ,当调用完所有的拦截器后,执行实际方法的调用
		if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
			return invokeJoinpoint();
		}

        // 执行各个拦截器的内容,进行Aop的逻辑处理
        // 如CacheInterceptor
		Object interceptorOrInterceptionAdvice =
				this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
		if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
			// Evaluate dynamic method matcher here: static part will already have
			// been evaluated and found to match.
			InterceptorAndDynamicMethodMatcher dm =
					(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
			Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
			if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
				return dm.interceptor.invoke(this);
			}
			else {
				// Dynamic matching failed.
				// Skip this interceptor and invoke the next in the chain.
				return proceed();
			}
		}
		else {
			// It's an interceptor, so we just invoke it: The pointcut will have
			// been evaluated statically before this object was constructed.
			return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
		}
	}

CglibMethodInvocation 里重写了invokeJoinpoint方法

		@Override
		protected Object invokeJoinpoint() throws Throwable {
			if (this.publicMethod && getMethod().getDeclaringClass() != Object.class) {
                // 这里会在target上进行调用相应的方法
				return this.methodProxy.invoke(this.target, this.arguments);
			}
			else {
				return super.invokeJoinpoint();
			}
		}

总结

通过以上的分析,实际是创建了一个动态代理的对象来拦截Spring注入的对象的所有调用,而创建的动态代理对象,是通过 DynamicAdvisedInterceptor进行处理的,这里会将调用的方法通过一些系列的处理后,将调用转到创建的原始的对象实例,而这个实例是没有经过任何处理的,所以当通过在代理对象调用的方法内部调用到了当前实例的方法,是没有进行代理的,也就是这个方法上的任务注解也是不生效的,再回到标题的问题,现在就可以理解了。

页面更新:2024-02-27

标签:方法   都会   初始化   实例   逻辑   原始   对象   动态   内容   信息

1 2 3 4 5

上滑加载更多 ↓
Top