How to use Spring Autowired (or manually connected) to a Scala object?

I am trying to use Spring with Scala. I know that Autowired works with the Scala class, but I use a web structure that requires an object, and I want to inject dao into it. I wonder how to do this? Sorry, I'm new to Scala, thanks in advance.

@Service object UserRest extends RestHelper { @Autowired @BeanProperty val userRepository: UserRepository = null; ..... } <beans> ..... <bean id="userRest" class="com.abc.rest.UserRest" > <!--- this is my attempt to manually wire it ---> <property name="userRepository" ref="userRepository"/> </bean> </beans> 
+7
source share
5 answers

Basically, you have two problems:

  • The property must be mutable, i.e. var , not val

  • All Scala object methods are static , while Spring expects instance methods. In fact, Scala creates a class with instance methods named UserRest$ behind the scene, and you need to make its singleton instance UserRest$.MODULE$ available for Spring.
    Spring can apply the configuration to existing instances of a singleton type, but they must be returned by the method, while UserRest$.MODULE$ is a field. So you need to create a method to return it.

So something like this should work:

 object UserRest extends RestHelper { @BeanProperty var userRepository: UserRepository = null; def getInstance() = this ... } 

.

 <bean id="userRest" class="com.abc.rest.UserRest" factory-method = "getInstance"> <property name="userRepository" ref="userRepository"/> </bean> 

You can replace <property> with @Autowired , but you cannot replace the bean declaration with the @Service due to problems with the singleton instance described above.

See also:

+12
source

All that is really needed is that you define your object as a class, not an object. This way Spring will instantiate.

  @Service object UserRest extends RestHelper { @Autowired @BeanProperty val userRepository: UserRepository = null; ..... } <beans> ..... <bean id="userRest" class="com.abc.rest.UserRest" > <!--- this is my attempt to manually wire it ---> <property name="userRepository" ref="userRepository"/> </bean> </beans> 

Changing β€œval” to β€œvar” is not required (Spring uses reflection, which ignores immutability). I'm sure this @BeanProperty is also not needed (Spring will refer to the base field, reflectively).

+4
source

The axtavt solution did not work for me, but by combining various sentences from other answers, I think this is the most elegant solution:

 object User { @Autowired val repo: UserRepository = null def instance() = this } @Configuration class CompanionsConfig { @Bean def UserCompanion = User.instance } <context:component-scan base-package="your-package" /> 

A few notes:

  • Using @Configuration ensures that your companion objects look autowired
  • Using @ Bean def eliminates the need to deal with noisy names. Scala gives a class that implements a companion object
  • val works great as Dave Griffith mentioned
  • no need for Scala @BeanProperty, Spring understands Scala properties out of the box (I use 3.2.2)
+3
source

I am using AutowiredAnnotationBeanPostProcessor to input an object at build time.

For example:

 object UserRest extends RestHelper { @Autowired var userRepository: UserRepository = _ AppConfig.inject(this) } @Configuration class AppConfig extends ApplicationListener[ContextRefreshedEvent] { // Set the autowiredAnnotationBeanPostProcessor when the Spring context is initialized def onApplicationEvent(event: ContextRefreshedEvent) { autowiredAnnotationBeanPostProcessor = event.applicationContext. getBean(AnnotationConfigUtils.AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME). asInstanceOf[AutowiredAnnotationBeanPostProcessor] } } object AppConfig { var autowiredAnnotationBeanPostProcessor: AutowiredAnnotationBeanPostProcessor = null def inject(obj: AnyRef) { autowiredAnnotationBeanPostProcessor.processInjection(obj); } } 

Now you can use AppConfig.inject () to enter any object whose life cycle is not controlled by Spring. For example, JPA objects, etc.

+1
source

In addition to https://stackoverflow.com/a/167374/ ... you can also add the scala package context to Spring, as well as the scala object , using the factory method. The compiled package object is a regular class java class called package, so you can add it to the Spring context. After that, you will have all the Spring features inside this object, i.e. @Autowired, @Value, manual wiring, etc.

Test package:

 package my.module package object A { def getInstance = this @Autowired private val b: B = null } 

And Spring xml context:

 <beans ...> ... <bean id="a" class="my.module.A.package" factory-method="getInstance"/> ... </beans> 
0
source

All Articles