如何在Groovy中构建可重新初始化的惰性属性?
发布时间:2020-12-14 16:23:02 所属栏目:大数据 来源:网络整理
导读:这就是我想做的事情: class MyObject { @Lazy volatile String test = { //initalize with network access }()}def my = new MyObject()println my.test//Should clear the property but throws groovy.lang.ReadOnlyPropertyExceptionmy.test = null //Sho
这就是我想做的事情:
class MyObject { @Lazy volatile String test = { //initalize with network access }() } def my = new MyObject() println my.test //Should clear the property but throws groovy.lang.ReadOnlyPropertyException my.test = null //Should invoke a new initialization println my.test 不幸的是,惰性字段是Groovy中的只读字段,清除属性会导致异常. 知道如何重新实现惰性字段,而无需重新实现@Lazy注释提供的双重检查逻辑吗? 更新: 考虑soft = true(从第一个答案开始)让我进行了一些测试: class MyObject { @Lazy() volatile String test = { //initalize with network access println 'init' Thread.sleep(1000) 'test' }() } def my = new MyObject() //my.test = null 10.times { zahl -> Thread.start {println "$zahl: $my.test"} } 大约1秒后,我的Groovy控制台上会有以下输出: init 0: test 7: test 6: test 1: test 8: test 4: test 9: test 3: test 5: test 2: test 这是预期的(和想要的).现在我添加soft = true,结果发生了显着变化,需要10秒钟: init init 0: test init 9: test init 8: test init 7: test init 6: test init 5: test init 4: test init 3: test init 2: test 1: test 也许我正在测试错误或soft = true完全破坏了缓存效果.有任何想法吗? 解决方法
你不能使用软
attribute of Lazy,即:
class MyObject { @Lazy( soft=true ) volatile String test = { //initalize with network access }() } 编辑 使用soft = true,注释会生成一个setter和一个getter,如下所示: private volatile java.lang.ref.SoftReference $test public java.lang.String getTest() { java.lang.String res = $test?.get() if ( res != null) { return res } else { synchronized ( this ) { if ( res != null) { return res } else { res = { }.call() $test = new java.lang.ref.SoftReference( res ) return res } } } } public void setTest(java.lang.String value) { if ( value != null) { $test = new java.lang.ref.SoftReference( value ) } else { $test = null } } 如果没有soft = true,你就不会得到一个setter private volatile java.lang.String $test public java.lang.String getTest() { java.lang.Object $test_local = $test if ( $test_local != null) { return $test_local } else { synchronized ( this ) { if ( $test != null) { return $test } else { return $test = { }.call() } } } } 所以变量是只读的.目前还不确定这是故意还是使用soft = true的副作用虽然… 编辑#2 这看起来可能是使用soft = true实现Lazy的一个错误 如果我们将getter更改为: public java.lang.String getTest() { java.lang.String res = $test?.get() if( res != null ) { return res } else { synchronized( this ) { // Get the reference again rather than just check the existing res res = $test?.get() if( res != null ) { return res } else { res = { println 'init' Thread.sleep(1000) 'test' }.call() $test = new java.lang.ref.SoftReference<String>( res ) return res } } } } 我认为它正在运作……我将开发一个修正错误 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |