spring/scala: Possible to autowire bean dependencies?

爱⌒轻易说出口 提交于 2019-12-08 12:09:46

问题


I'm trying do the following without xml configuration in spring (in scala)

<beans ... >
   ## (1)
   ## Auto create a bean by classname
   ## Auto-wires properties of x.y.Bar
   <bean id="baz" class="x.y.Baz"/>

   ## (2)
   ## Create a x.y.Foo and auto-wire the property
   <bean id="foo" class="x.y.Foo">
      <property name="b" ref="baz"/>
   </bean>
</beans>

where we have:

 class Baz {}

 class Foo {
   @Autowired   //?
   @BeanProperty
   val baz:Baz = null
 }

I have the following test setup:

 @Configuration
class Config {
  //@Autowired  // Seem not to help
  @Bean //( autowire=Array( classOf[Autowire.BY_TYPE ]) )
  def foo: Foo = null
}

class BeanWithAutowiredPropertiesTest {

  @Test
  @throws[Exception] def beanWithAutowiredPropertiesTest(): Unit = {
    var ctx = new AnnotationConfigApplicationContext(classOf[Config]);
    val foo = ctx.getBean(classOf[Foo])
    assertTrue(foo != null)
    assertTrue(ctx.getBean(classOf[Foo]).baz != null)
  }
}

I understand a couple of simple alternatives:

  • @ComponentScan -- this approach has several issues:

    • imprecision - there can be many classes matching an auto-wired type in a package
    • it doesn't (in itself) permit selecting specific values for properties
    • scanning is painfully slow for large projects
    • Can't add @Component to 3rd party classes

      (If I could register candidate auto-wire types, by name, that would help a lot!)

  • implementing the @Bean declaration as a method:

.

  @Bean
  def foo:Foo = {
     val f = new Foo()
     f.baz = ?? grrr! where from? Not available in this Config 
     f
  }

However:

  • this sorta circumvents the point of auto-wiring. If I explicitly chose a parameter, baz to set, then I need to actually get a reference to it to do that in the first place. Frequently this can be difficult, especially if the actual baz to be used might be specified in another @Configuration.

  • because I'm creating the object, don't I need to auto-wiring all of its dependencies? What if Baz has 100 properties and I only way to specify 1 explicitly and have the rest auto-wired?

AFAIK, the xml based configuration doesn't have any of these problems - but I'm at a loss because the spring manual says you can do all the same things via annotations.

NB. I also see:

@Bean( autowire=Array( classOf[Autowire.BY_TYPE ]) )

might be possible. I can't find example online, and scala complains (annotation parameter is not a constant).


回答1:


[edited]

class ApplicationController @Inject() (messagesApi: MessagesApi){
  ... code here ...
}

messagesApi is an injected member

see more in https://github.com/mohiva/play-silhouette-seed/blob/master/app/controllers/ApplicationController.scala


[before edit]

I'v found this to be usefull

Answered by Joshua.Suereth. This is the short version ("ugly but works"):

var service: Service = _; 
@Autowired def setService(service: Service) = this.service = service



回答2:


For automatic bean creation you need to annotate the classes as Component, Service or Persistence, in addition to enabling the ComponentScan at config level.

So you can try:

@Component
class Baz {}

@Component
class Foo {
   @Autowired   //?
   @BeanProperty
   val baz:Baz = null
 }

For multiple classes implementing the same interface, you can specify names to both the component and the dependency references, i.e.

@Component("baz1")
class Baz {}

@Component("foo1")
class Foo {
   @Resource("baz1")   //?
   @BeanProperty
   val baz:Baz = null
 }

Notice the @Autowire has been replaced by @Resource.



来源:https://stackoverflow.com/questions/25336368/spring-scala-possible-to-autowire-bean-dependencies

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!