先来看以下的代码
@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
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
本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828
© CopyRight 2008-2024 All Rights Reserved. Powered By bs178.com 闽ICP备11008920号-3
闽公网安备35020302034844号