3

I'm trying to inject an existing bean into a Groovy class and I know Grails bean injection doesn't work for normal Groovy classes (in src/groovy folder). I can get access to a bean via

Holders.applicationContext.getBean('beanName')

However, I'm wondering if this is the best approach (from a execution speed and memory usage point of view). I will be calling a bean from a method that's called hundreds of times during the normal use of the application and I'm wondering if there might be a better approach. At the very least, should I be storing the bean reference (maybe in the constructor) so that I don't call the above code over and over again? Could I store a static reference to the bean so that each class doesn't have to store its own? Any other suggestions or improvements?

Burt Beckwith
  • 75,342
  • 5
  • 143
  • 156
Harry Muscle
  • 2,247
  • 4
  • 38
  • 62

2 Answers2

2

Your Groovy (or Java) class cannot use dependency injection, but it is very likely called directly or indirectly from a class that can, e.g. a controller or a service. Rather than having this class pull in its dependencies (which runs pretty strongly against the ideas of dependency injection and inversion of control), pass into the class the beans that it needs, or at a minimum the ApplicationContext if the beans aren't always known up front.

So for example rather than doing this in your service (where Thing is your src/groovy class):

def someServiceMethod(...) {

   def thing = new Thing()
   thing.doSomething(42, true)

}

add a dependency injection for the bean it needs in the service and pass it along with the other args, either in the constructor or in individual methods, e.g.

class MyService {

   def someBean

   def someServiceMethod(...) {

      def thing = new Thing(someBean)
      thing.doSomething(42, true)

   }
}
Burt Beckwith
  • 75,342
  • 5
  • 143
  • 156
1

Groovy classes in src/groovy are not picked up for dependency injection by default. But you can configure them manually by adding a bean definition to conf/spring/resources.groovy:

import your.class.from.src.groovy.MyBean
beans = {
    myBean(MyBean)
}

Using this way you can configure how dependencies should be resolved. You can do this manual, e.g.

myBean(MyBean) {
  myService = ref('myService') // assumes you have a MyService bean that can be injected to the `myService` field
}

Or you can use autowiring (what grails does by default for services/controllers):

myBean(MyBean) { bean ->
  bean.autowire = 'byName'
}

By adding beans to resources.groovy you can also inject these beans into services and controllers.

For more details see the Spring section in the Grails documentation

micha
  • 47,774
  • 16
  • 73
  • 80
  • I will clarify my original question, but it's actually about doing the opposite of what you mention. I'm trying to inject an existing bean into a normal Groovy class. Not inject a normal Groovy class into a service or controller. Thanks. – Harry Muscle Sep 23 '14 at 15:39
  • It works in both directions. By adding a bean to resources.groovy you tell spring about this bean. So spring can inject other beans into this bean and this bean can be injected into other bean. – micha Sep 23 '14 at 15:41
  • This doesn't help, it's a circular solution. Now his class can access other beans since it's a bean, but how does he get access to the bean for his class? – Burt Beckwith Sep 23 '14 at 23:21