当前位置: 首页 > news >正文

怎么用电脑做网站吴江seo排名

怎么用电脑做网站,吴江seo排名,嘉峪关市网站建设设计,国家企业信用信息系统公示查询官网一、Async 注解下的循环依赖问题 我们都知道 Spring IOC 单例模式下可以帮助我们解决循环依赖问题#xff0c;比如下面自己依赖自己循环依赖的场景#xff1a; Component public class TestAsync {ResourceTestAsync async;public void test() {System.out.println(t…一、Async 注解下的循环依赖问题 我们都知道 Spring IOC 单例模式下可以帮助我们解决循环依赖问题比如下面自己依赖自己循环依赖的场景 Component public class TestAsync {ResourceTestAsync async;public void test() {System.out.println(test....);} }从容器中获取到该 bean 执行测试方法 public class App {public static void main(String[] args) {ApplicationContext context new AnnotationConfigApplicationContext(com.demo.test);TestAsync testAsync context.getBean(testAsync, TestAsync.class);testAsync.test();}}可以看到正常执行但当我们加上 Async 注解后 Component EnableAsync public class TestAsync {ResourceTestAsync async;Asyncpublic void test() {System.out.println(test....);} }再次执行发现报错了 是不是很奇怪难道代理对象就会有问题吗如果换成 Transactional 呢 Component EnableTransactionManagement public class TestAsync {ResourceTestAsync async;Transactionalpublic void test() {System.out.println(test....);} }再次执行发现可以正常运行 那为什么 Async 会有问题呢其实和我们上篇文章中讲解的 BeanPostProcessor 扩展接口有关这里先说一下解决方法 将依赖注入换成懒加载的方式即可 Component EnableAsync public class TestAsync {ResourceLazyTestAsync async;Asyncpublic void test() {System.out.println(test.... Thread.currentThread().getName());} }可以看到恢复正常了下面从源码角度分析下出现该问题的原因。 如果不了解 BeanPostProcessor 扩展接口可以先看下下面这篇文章 Spring 源码解析 - BeanPostProcessor 扩展接口 二、源码分析 2.1 EnableAsync 当使用 EnableAsync 开启异步支持时会向 Spring 容器中注入AsyncConfigurationSelector.class 类 在该类中selectImports 下根据 adviceMode 选择注入配置类adviceMode 默认为 PROXY会注入 ProxyAsyncConfiguration.class 配置类 在 ProxyAsyncConfiguration.class 配置类下注入了一个 AsyncAnnotationBeanPostProcessor 扩展类 下面看下AsyncAnnotationBeanPostProcessor 扩展类的继承树 AsyncAnnotationBeanPostProcessor 从 BeanPostProcessor 获得bean初始化前后的扩展能力从 ProxyProcessorSupport 获取代理能力。 这里重点看 BeanPostProcessor 扩展在 BeanPostProcessor 中有两个核心的扩展方法如下 public interface BeanPostProcessor {/*** 实例化及依赖注入完成后、bean 初始化方法触发之前执行*/Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;/*** bean 初始化方法触发后执行*/Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;}下面看挨个看AsyncAnnotationBeanPostProcessor中这两个方法干了什么 在AsyncAnnotationBeanPostProcessor没有直接实现 postProcessBeforeInitialization 实现在 AbstractAdvisingBeanPostProcessor 下的 postProcessBeforeInitialization 方法 没有做任何操作直接返回的原 bean 同样 postProcessAfterInitialization 方法也在 AbstractAdvisingBeanPostProcessor 下 在这里实际生成了代理 bean 进行返回。 到这我们需要记住 AsyncAnnotationBeanPostProcessor 的postProcessBeforeInitialization 前通知没有做任何操作 postProcessAfterInitialization 后通知创建了代理实例。 2.2 getEarlyBeanReference 了解过循环依赖的应该知道 Spring 中使用三级缓存来解决循环依赖问题其中实例化 bean 后会首先曝光至第三级缓存中该逻辑在 AbstractAutowireCapableBeanFactory 类的 doCreateBean 方法下 在 doCreateBean 方法下的 populateBean 主要是进行了依赖的注入 在进行依赖注入时会递归尝试从三级缓存中获取 bean 由于这里是循环依赖已经放入了第三级缓存中因此可以命中这快的源码逻辑在 DefaultSingletonBeanRegistry 类下的 getSingleton 方法 这里可以看出三级缓存命中会执行 ObjectFactory.getObject() 方法获取一个早期的实例获取之后存入二级缓存中从前面放入三级缓存可以看出其实是触发的 AbstractAutowireCapableBeanFactory 下的 getEarlyBeanReference 方法 这里会判断是否存在 SmartInstantiationAwareBeanPostProcessor 类型的 BeanPostProcessor 扩展然后尝试使用 getEarlyBeanReference 获取一个早期的实例从前面 AsyncAnnotationBeanPostProcessor 的继承树可以看出并没有实现 SmartInstantiationAwareBeanPostProcessor 因此这里拿到的就是原来的 bean 实例 到这里我们需要记住Spring 单例缓存中存储的是 TestAsync 真正的实例对象。 2.3 initializeBean 在依赖注入后会触发 initializeBean 方法进行 bean 的初始化操作 在 initializeBean 方法中执行初始化前先执行BeanPostProcessors的前置方法并且将前置方法返回的 bean 代替原先创建的 bean 在 bean 初始化后执行BeanPostProcessors的后置方法并将后置方法返回的 bean 代替原先的 bean从上面对 AsyncAnnotationBeanPostProcessor的简单分析得出前置方法没做任何处理后置方法会生成一个代理对象因此initializeBean 方法最终返回的是代理对象 可以看出最后生成的是一个代理对象现在应该就会发现一个问题了在 Spring 单例容器中和依赖注入中的都是 TestAsync 真正的实例而这里返回的是代理实例现在相当于单例的 bean 存在了两个不同的实例。 2.4 判断是否出现重复实例 在回到 doCreateBean 方法下 initializeBean 执行后 如果是单例的话则尝试从容器中获取当前的 beanName 实例由于前面已经曝光到了二级缓存中因此这里可以获取到但容器中的bean实例和当前的 bean实例已经不是一个实例了因此会进入到 else if 中这里获取到该 beanName 所有的依赖通过 removeSingletonIfCreatedForTypeCheckOnly 删除已经创建好的 bean 实例因为单例模式下 Spring 仅允许有一个实例这里可以看下 removeSingletonIfCreatedForTypeCheckOnly 方法的逻辑 这里主要判断 alreadyCreated 中是否存在如果不存在则删除单例缓存中的实例那 alreadyCreated 什么时候放入的呢其实在AbstractAutowireCapableBeanFactory 类的 doGetBean 方法中触发的 markBeanAsCreated 方法 因此 removeSingletonIfCreatedForTypeCheckOnly 方法这里会返回 false在回到 doCreateBean 中继续看由于 removeSingletonIfCreatedForTypeCheckOnly 返回 false 正好符合条件被加入了 actualDependentBeans 集合中再下面如果actualDependentBeans 集合不为空则抛出异常这个异常是不是和之前报错的异样一样 三、为什么 Transactional 不会出现这种问题呢 从上面的分析可以得出结论假如 getEarlyBeanReference 可以获取到代理实例是不是就不会发生后面的问题这恰恰也是 Transactional 情况下的不会出现该问题的关键点。 Transactional 代理使用的是 InfrastructureAdvisorAutoProxyCreator 从 InfrastructureAdvisorAutoProxyCreator的继承树可以看到其继承了 SmartInstantiationAwareBeanPostProcessor 方法。并且在父类 AbstractAutoProxyCreator 中重写了 getEarlyBeanReference 方法 下面可以 debug 一下 AbstractAutowireCapableBeanFactory 中的 getEarlyBeanReference 方法 可以看到这里还是真正的实例对象下面会进到 AbstractAutoProxyCreator 中重写的 getEarlyBeanReference 方法最终进到当前类的 wrapIfNecessary 方法 到这里就已经生成了一个代理类了再回到 AbstractAutowireCapableBeanFactory 中的 getEarlyBeanReference 方法中这时返回的就是代理类了。
http://www.w-s-a.com/news/697558/

相关文章:

  • 设计企业网站内容wordpress 投稿者 权限
  • seo网站推广免费价格低的成语
  • 做网站建设销售辛苦吗专题页是什么
  • 做网站的软件名字全拼wordpress可以上传文件吗
  • 建品牌网站公司关于asp_sql网站开发的书籍
  • 建网站公司营销型网站建设wordpress自定义登录页
  • 泉州市住房和城乡建设局网站淘宝店网站怎么做
  • 企业网站建设费未付款怎样挂账长春网站制作专业
  • 深圳找网站建设邹城市建设局网站
  • 长春火车站停运了吗网站开发概要设计
  • 网站开发表格整体页面居中网站域名详解
  • 漕泾网站建设赢展网站建设
  • 医院网站建设的要求毕业了智慧团建密码忘了
  • 网站怎么建设在哪里接单坪山商城网站建设哪家便宜
  • 中山企业网站优化易语言wordpress发布
  • 宜昌网站推广自己怎么做彩票网站吗
  • 英文网站建设 招标网站建设中服务器搭建方式
  • 直播网站建设需要什么软件有哪些室内设计效果图怎么做
  • 宁波网站建设电话网络推广外包一年多少钱
  • 检索标准的网站怎么制作企业网站
  • 下列关于网站开发中网页发布wordpress 粘帖图片
  • 网站建设遇到的问题及对策宁波网站建设营销推广
  • 各大招聘网站常州百度快速优化
  • 做网站线稿软件有哪些做门户网站需要注册公司吗
  • 建设企业网站模板下载优化方案怎么写
  • 做像淘宝网的网站网站单页面制作
  • 网站建设流程表龙岩网站建设较好的公司
  • 龙岗建站费用手机免费建立网站吗
  • 江门高端网站建设怎样制作wordpress手机主题
  • 淘宝网站如何在邮件里做超链接wordpress图片投票插件