Scala Spring @Value in the designer body

I have the following spring wired scala class with pseudo code.

@Service class Something { @Value("${some.property}") val someString : String // do something with someString in the body } 

However, this will not work, because someString is part of the body of the constructor, and spring cannot connect to the values ​​until it executes the constructor.

How can I connect to @Value so that it works, and is not terrible (my current solution with a custom constructor containing all the values ​​I need, just does not feel "scala" and looks awful.

Edit: To clarify, my current solution is this:

 @Service class Something { @Autowired def this(@Value("${some.prop}") prop : String) { this() // do other construction stuff here } } 

I just think it looks ugly and feels that there is a better way. I also do not like to create these secondary constructors when I prefer to use it in the main constructor.

Edit 2: To clarify, I was hoping there was a way to do something like this:

 @Service class Something(@Value("${some.property}") string : String) { // use the value in your constructor here } 

Because it looks a lot more elegant. I just can't get it to work :)

+4
source share
2 answers

Well, after everything back and forth, I think I understand better what you want, so I take it on myself:

 import scala.annotation.BeanProperty import scala.annotation.target.beanSetter class Something @Autowired() (@(Value @beanSetter)("{some.property}") @BeanProperty var prop: String) 

This is essentially Paolo Falabella's solution, except that I try to avoid using Spring private fields. To this end, I let scala auto- @BeanProperty public java-like setter using @BeanProperty and apply @Value on it. You can also improve the syntax a bit using an alias like:

 type Value = org.springframework.beans.factory.annotation.Value @beanSetter @beanGetter class Something @Autowired() ( @ BeanProperty@Value ("{some.property}") var prop: String) 
+4
source

You need to initialize someString to a value so that a real field is generated in the class. Alternatively, you can use var instead of val , but you will have to initialize it anyway.

For instance:

 @Service class TestService { @Value("${testService.foo:bar}") val foo: String = null //var foo: String = _ } 

To decompile the TestService.class file, you will see that it places the annotation in the private final String field (you can also use jclasslib byte viewer ):

 @Service @ScalaSignature(bytes="\006\001!3A!\001\002\001\023\tYA+Z:u'\026\024h/[2f\025\t\031A!\001\005tKJ4\030nY3t\025\t)a!A\002osbT\021aB\001\004G>l7\001A\n\004\001)\021\002CA\006\021\033\005a!BA\007\017\003\021a\027M\\4\013\003=\tAA[1wC&\021\021\003\004\002\007\037\nTWm\031;\021\005M1R\"\001\013\013\003U\tQa]2bY\006L!a\006\013\003\027M\033\027\r\\1PE*,7\r\036\005\0063\001!\tAG\001\007y%t\027\016\036 \025\003m\001\"\001\b\001\016\003\tAqA\b\001C\002\023\005q$A\002g_>,\022\001\t\t\003C\021r!a\005\022\n\005\r\"\022A\002)sK\022,g-\003\002&M\t11\013\036:j]\036T!a\t\013\t\r!\002\001\025!\003!\003\0211wn\034\021)\t\035R\003(\017\t\003WYj\021\001\f\006\003[9\n!\"\0318o_R\fG/[8o\025\ty\003'A\004gC\016$xN]=\013\005E\022\024!\0022fC:\034(BA\0325\003=\031\bO]5oO\032\024\030-\\3x_J\\'\"A\033\002\007=\024x-\003\0028Y\t)a+\0317vK\006)a/\0317vK\006\n!(\001\f%wR,7\017^*feZL7-\032\030g_>T$-\031:~\021\025a\004\001\"\001>\003)Ig.\033;jC2L'0\032\013\002}A\0211cP\005\003\001R\021A!\0268ji\"\022\001A\021\t\003\007\032k\021\001\022\006\003\013J\n!b\035;fe\026|G/\0379f\023\t9EIA\004TKJ4\030nY3") public class TestService implements ScalaObject { @Value("${testService.foo:bar}") private final String foo; public String foo() { return this.foo; } public TestService() { null; this.foo = null; } } 

I use @Value for class members all the time, it is very convenient.

+3
source

Source: https://habr.com/ru/post/1442767/


All Articles