上面找到了AOP入口的位置,那么接下来就需要判断对象是否需要AOP增强。
判断过程:
wrapIfNecessary 判断是否需要对目标对象设置代理对象,不需要的话直接返回原始对象即可:
- 首先从 targetSourcedBeans 缓存中判断,如果包含目标对象的话,就返回了;
- 从 advisedBeans 缓存()中判断,如果不需要代理的话也直接返回了;
- 判断是否为 AOP 相关接口的实现类(Pointcut、Advice、Advisor),这些不需要代理;
- 获取增强用的拦截器们;如果为空的话,那说明也不需要代理;
- 那么上面的条件都符合了,就进入createProxy 先创建代理工厂阶段;
:::success
缓存:
// 存放自定义代理对象
private final SettargetSourcedBeans = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
// 存放基础设施类比如:Pointcut、Advice、Advisor
private final Map
具体源码:
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 判断名称不为空,并且代理对象已经存在,那么直接返回
// targetSourcedBeans 在createBean阶段中的 resolveBeforeInstantiation 可能被处理
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// 根据缓存(不需要代理的bean的集合)判断
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
// 如果是基础设施类(Pointcut、Advice、Advisor 等接口的实现类);或是应该跳过的类,则不成代理
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
// 获取方法的拦截代理对象
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
// bean加入缓存,表示已代理
this.advisedBeans.put(cacheKey, Boolean.TRUE);
/*
创建代理对象
bean.getClass():被代理对象的Class对象
beanName:被代理对象名称
specificInterceptors:被代理对象方法的增强方法
new SingletonTargetSource(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;
}