共计 6205 个字符,预计需要花费 16 分钟才能阅读完成。
前言
开启 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; }
-
创立代理的外围办法:
createProxy
(基于ProxyFactory
)。其中真正的创立代理对象的办法是ProxyFactory.getProxy
办法;
/** * Create a new proxy according to the settings in this factory. * <p>Can be called repeatedly. Effect will vary if we've added * or removed interfaces. Can add and remove interceptors. * <p>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 =true fasle 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()
获取到的就是这个单例池中的代理对象。
后续思考针对 AOP 的一些优化措施,特地是盘绕告诉,在遇到所有 AOP 的性能瓶颈点的时候根本都是盘绕告诉。