上面找到了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;}
