前言
? 开启AOP功能后,AOP的逻辑是如何开始进行的。
一、Bean的生命周期
? 要讲AOP就必须了解Spring Bean的生命周期,AOP的逻辑是在Bean初始化后这个阶段开始的。Spring Bean的生命周期简单上图:
文章图片
二、AOP
(一)@EnableAspectJAutoProxy
? Spring中使用该注解开启AOP功能。该注解会注册一个AutoProxyCreator
【AnnotationAwareAspectJAutoProxyCreator
、AspectJAwareAdvisorAutoProxyCreator
】相关的类到IOC容器中,AutoProxyCreator
相关的类实现了InstantiationAwareBeanPostProcessor
接口,即在Bean实例化前后会执行AOP的一些前置准备操作。
- 其中
AbstractAutoProxyCreator
实现了BeanFactoryAware
接口,是我们事务和aop导入进来的后置处理器的顶级父类; - 在
AbstractAutoProxyCreator
postProcessBeforeInstantiation
实例化前方法中,会进行AOP切面Bean
的缓存(是Advice
、PointCut
、Advisor
基础Bean类型就直接跳过不解析);
/**AbstractAutoProxyCreator * 在我们的创建Bean的流程中还没调用构造器来实例化bean的时候进行调用(实例化前后) * 我们的aop 解析切面 以及事务解析事务注解都是在这里完成的 * @param beanClass 当前正在创建的bean的class对象 * @param beanName beanName * @return * @throws BeansException */ @Override public Object postProcessBeforeInstantiation(Class> beanClass, String beanName) throws BeansException { //构建我们的缓存key Object cacheKey = getCacheKey(beanClass, beanName); if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) { //如果被解析过 直接返回 if (this.advisedBeans.containsKey(cacheKey)) { return null; } /** * 判断是不是基础的bean * 判断是不是应该跳过 (aop解析直接解析出我们的切面信息(并且把我们的切面信息进行保存),而事务在这里是不会解析的) */ if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return null; } }/** * 这个地方一般是不会生成代理对象的,除非我们的容器中有TargetSourceCreator 并且我们的bean需要实现 * TargetSource接口 */ TargetSource targetSource = getCustomTargetSource(beanClass, beanName); if (targetSource != null) { if (StringUtils.hasLength(beanName)) { this.targetSourcedBeans.add(beanName); } Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; }return null; }
(二)创建Proxy代理对象
- 在
AbstractAutoProxyCreator
postProcessAfterInitialization
初始化后方法中【每个Bean在创建的时候都会调用】,会进行AOP代理对象的创建,主要方法:wrapIfNecessary
;
/**AbstractAutoProxyCreator * 在该后置方法中,AOP的代理对象在这生成 * @param bean bean实例 * @param beanName bean的名称 * @return * @throws BeansException */ @Override public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException { if (bean != null) { //获取缓存key Object cacheKey = getCacheKey(bean.getClass(), beanName); if (this.earlyProxyReferences.remove(cacheKey) != bean) { //找到合适的就会被代理 return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; }
wrapIfNecessary
方法如下:
/**AbstractAutoProxyCreator wrapIfNecessary * Wrap the given bean if necessary, i.e. if it is eligible for being proxied. * @param bean the raw bean instance * @param beanName the name of the bean * @param cacheKey the cache key for metadata access * @return a proxy wrapping the bean, or the raw bean instance as-is */ protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { //已经被处理过 if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { return bean; } //不需要增强的 if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } //是不是基础的bean 是不是需要跳过的 if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; }//如果我们有通知的话,就创建代理对象 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); //我们的合适的通知器不为空 if (specificInterceptors != DO_NOT_PROXY) { //表示当前的对象已经代理模式处理过了 this.advisedBeans.put(cacheKey, Boolean.TRUE); //创建我们的真正的代理对象 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; }
- 【Spring AOP源码学习(AOP的入口)】创建代理的核心方法:
createProxy
(基于ProxyFactory
)。其中真正的创建代理对象的方法是ProxyFactory.getProxy
方法;
/** * Create a new proxy according to the settings in this factory. * Can be called repeatedly. Effect will vary if we've added * or removed interfaces. Can add and remove interceptors. * Uses the given class loader (if necessary for proxy creation). * @param classLoader the class loader to create the proxy with * (or {@code null} for the low-level proxy facility's default) * @return the proxy object */ public Object getProxy(@Nullable ClassLoader classLoader) { //createAopProxy() 用来获取我们的代理工厂 return createAopProxy().getProxy(classLoader); }
createAopProxy
方法会判断使用JDK
动态代理还是CGLIB
CGLIB
代理方式在第一次执行AOP操作的时候可能耗时会比较长,因为需要生成新的字节码文件;- 总的情况,
CGLIB
和JDK
的方式性能都差不多;但是相比使用原生的AspectJ
,性能还是要差上一些。AspectJ
是基于字节码编制技术,不借助于Proxy对象实现。
/** * 实现类DefaultAopProxyFactory createAopProxy * @param config 用来为我们指定我们advisor信息 * 该方法用来创建我们的代理对象 * 所我们的targetClass对象实现了接口,且ProxyTargetClass 没有指定强制的走cglib代理,那么就是创建jdk代理 * 我们代理的类没有实现接口,那么会直接走cglib代理 * 若我们ProxyTargetClass 指定为false 且代理类是接口才会走jdk代理 否在我们还是cglib代理 * @return * @throws AopConfigException */ @Override public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { //判断我们是否前置指定使用cglib代理ProxyTargetClass =truefasle 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."); } //所targetClass是接口 使用的就是jdk代理 if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } //cglib代理 return new ObjenesisCglibAopProxy(config); } else { //动态代理 return new JdkDynamicAopProxy(config); } }
// 实现类JdkDynamicAopProxy getProxy方法 @Override public Object getProxy(@Nullable ClassLoader classLoader) { if (logger.isDebugEnabled()) { logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource()); } Class>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true); findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); }/** * Finds any {@link #equals} or {@link #hashCode} method that may be defined * on the supplied set of interfaces. * @param proxiedInterfaces the interfaces to introspect */ private void findDefinedEqualsAndHashCodeMethods(Class>[] proxiedInterfaces) { for (Class> proxiedInterface : proxiedInterfaces) { Method[] methods = proxiedInterface.getDeclaredMethods(); for (Method method : methods) { if (AopUtils.isEqualsMethod(method)) { this.equalsDefined = true; } if (AopUtils.isHashCodeMethod(method)) { this.hashCodeDefined = true; } if (this.equalsDefined && this.hashCodeDefined) { return; } } } }
创建完的代理对象就会保存到DefaultSingletonBeanRegistry
的单例池singletonObjects
中,之后getBean()
获取到的就是这个单例池中的代理对象。