在@Bean上加上了@RefreshScope注解爆Unable to start web server; nested exception is org.springfram?

最近在读《深入理解Java虚拟机》,对Java对象的内存布局有了进一步的认识,于是脑子里自然而然就有一个很普通的问题,就是一个Java对象到底占用多大内存?

想弄清楚上面的问题,先补充一下基础知识。

在 HotSpot虚拟机中,对象在内存中的存储的布局可以分为三块区域:对象头(Header),实例数据(Instance Data)和对齐填充(Padding)

某些情况下,JVM根本就没有把Object放入堆中。例如:原则上讲,一个小的thread-local对象存在于栈中,而不是在堆中。
被Object占用内存的大小依赖于Object的当前状态。例如:Object的同步锁是否生效,或者,Object是否正在被回收。
我们先来看看在堆中单个的Object长什么样子
在堆中,每个对象由四个域构成(A、B、C 和 D),下面我们逐个解释一下:
A:对象头,占用很少的字节,表述Object当前状态的信息
C:引用类型域占用的空间(引用类型域指 其他对象的引用,每个引用占用4个字节)
D:填充物占用的空间(后面说明什么是填充物)



对象=对象头+成员变量+对齐填充

对象头结构:java对象在Heap里面的结构是这样的:对象头跟对象体,对象体跟C里面的结构体是一样的,对象头由两个域组成:用于存放hashcode、同步、GC的_mask域,和指向方法区该对象Class对象的指针——_klass域,对于64位系统,头部长度理论上讲应该是8+8=16字节。但是从java6u23以后开始,64位的机器会自动开启指针压缩的功能,此时引用指针的长度为4字节。所以,对象头长度应该为8+4=12。

接下来让我们计算一下这个map多占用的空间

next :因为就只有一个元素,所以next值为null,0字节

Zuul对接Web网站的时候,处理完了会话控制问题之后。往往我们还会碰到如下图所示的问题,我们在浏览器中通过Zuul发起了登录请求,该请求会被路由到某WebSite服务,该服务在完成了登录处理之后,会进行重定向到某个主页或欢迎页面。此时,仔细的开发者会发现,在登录完成之后,我们浏览器中URL的HOST部分发生的改变,该地址变成了具体WebSite服务的地址了。这就是在这一节,我们将分析和解决的重定向问题!

  很明显该方法是将Environment绑定到对应SpringApplication上,通过这个类就可以获取到我们更改过后的配置了

  changes方法其实就是处理配置变更信息的,分以下几种情况:

  1)如果刷新过后配置文件新增配置就添加到Map里

  2)  如果有配置变更就添加变更后的配置

  3) 如果删除了原先的配置,就把原先的key对应的值设置为null

  至此经过changes方法后,上下文环境已经拥有最新的配置了。

  当上述步骤都执行完毕后,紧接着会发布EnvrionmentChangeEvent事件,可是这个事件谁来监听呢?在这里我贴出官网的一段描述:

  根据官网描述我们知道将变更一下操作行为@ConfigurationProperties的bean与更改日志level,那么如何做到的呢?结合官网文档我们来关注以下两个类:

  我们可以看到该类监听了ChangeEnvrionmentEvent事件,它最主要作用是拿到更新的配置以后,重新绑定@ConfigurationProperties标记的类使之能够读取最新的属性

  我们考虑如下场景,当我们变更数据库配置后,通过refresh刷新,虽然能获取到最新的配置,可是我们的DataSource对象早就被初始化好了,换句话说即便配置刷新了我们拿到的依然是配置刷新前的对象。怎么解决这个问题呢?

  当配置更改时,标有@RefreshScope的Spring @Bean将得到特殊处理。这解决了状态bean在初始化时只注入配置的问题。例如,如果通过Environment更改数据库URL时DataSource有开放连接,那么我们可能希望这些连接的持有人能够完成他们正在做的工作。然后下一次有人从游泳池借用一个连接,他得到一个新的URL
  

   刷新范围bean是在使用时初始化的懒惰代理(即当调用一个方法时),并且作用域作为初始值的缓存。要强制bean重新初始化下一个方法调用,您只需要使其缓存条目无效。RefreshScope是上下文中的一个bean,它有一个公共方法refreshAll()来清除目标缓存中的范围内的所有bean。还有一个refresh(String)方法可以按名称刷新单个bean。此功能在/refresh端点(通过HTTP或JMX)中公开。

  这里面创建了一个名字为refresh的scope。

  紧接着在它的父类里我们可以看一下这个方法:

  这里的代码逻辑很简单清除与释放缓存里被@RefreshScope标记的bean 。

  当我们要获取对象时,我们可以关注如下方法:

  创建AppConfig类代码如下:

   这里把refresh端点开放出来,然后变更配置后就可以获取最新的对象了

Spring Cloud是分布式微服务架构的一站式解决方案,是多种微服务架构落地技术的集合体,俗称微服务全家桶。
服务注册与发现:Eureka







7.3.1 俩个主要接口介绍

全局日志记录、统一网关鉴权…

我要回帖

更多关于 语文书上狼的注解 的文章

 

随机推荐