Dependency Injection with Grails Spring DSL - spring

When I use the Spring DSL provided by Grails is it possible to do constructor injection. If so, an example would be much appreciated.
If constructor injection is not possible, is there some other way that I can inject a spring bean without making the dependencies public properties. Using Spring in a Java project I can do this
class Foo {
#Autowired
private Bar bar
}
And it will autowire the Bar dependency either by name or type

it is possible to use constructor injection even using the BeanBuilder DSL
bb.beans {
exampleBean(MyExampleBean, "firstArgument", 2) {
someProperty = [1,2,3]
}
}
whenever you want to reference other beans as constructor arguments, use the ref() method
bb.beans {
exampleBean(MyExampleBean, "firstArgument", ref('anotherBean')) {
someProperty = [1,2,3]
}
}

You should be able to inject a bean into the constructor using the #Autowired annotation like you'd usually do in Spring. Here's an example:
class Foo {
private final Bar bar
#Autowired
public Foo(Bar bar) {
this.bar = bar
}
}

Related

Spring custom annotation for bean injection

I am looking to inject a bean by means of a custom annotation
#Service
class Foo(#MyBean val bar: Bar) { fun someMethod() { bar.invoke() } }
with
#Retention(AnnotationRetention.RUNTIME)
#Target(AnnotationTarget.PROPERTY, AnnotationTarget.VALUE_PARAMETER)
annotation class MyBean
Currently we have a configuration class that defines multiple bean methods
#Configuration
class config {
#Bean
fun bar(): Bar = { getBaz() }
}
I have seen implementations of BeanPostProcessor but that seems to add behaviour to already existing beans. My question is, is there a way to initialise and assign beans to a field by means of a custom annotation.
Since you're injecting the field through a constructor, you don't need to annotate the field itself, but rather the constructor.

Inject constructor parameter by custom annotation in spring?

In spring, injecting custom non-autowirable value to fields/setter can be processed by BeanPostProcessor, like:
class Foo
{
#MyAnnotation
SomeService sth;
}
But, in constructor parameter, seems no any extension for customizing injection, only #Value or #Qualifier accepted, which is implemented by spring framework core.
class Foo
{
Foo(
#Value("sth") String sth, // OK
#Qualifier("foo") Foo foo, // OK
#MyAnnotation SomeService sth // Bad!
) { ... }
}
Is there any way to achieve this goal?

Spring : Autowire

If I initialize one object manually ,inside that class I have autowired some of the other classes , Does spring creates and instances of Autowired objects ?
Example :
Class A {
#Autowired
B b;
}
Class main {
main(){
A a = new A();
//Does spring initialize B class also automatically(Autowired)?
}
}
No, Class A by itself has to be managed by spring as well as class B
In general Autowiring works only for classes that are managed by spring

Conditionally auto-wire a bean implementation based on a value?

I have an interface Animal having two implementations Cat and Dog. These two implementations are spring #Component. How do I conditionally wire these two based on a value? I understand that I may have to change the scope of MyTestController from singleton to request.
#RestController
public class MyTestController {
#Autowired
Animal animal;// how to wire bean of Cat or Dog based on animalName
#PostMapping("/get-animal")
public #ResponseBody Animal getAnimal(#RequestParam(value = "animalName") String animalName) {
return animal;
}
}
Since both MyTestController is a bean the autowiring / initialisation happens before you actually start using the class instance itself. What I mean is that by the time you actually trigger REST requests on your controller, the injected animal bean should be already there!
More specifically if you have two classes that implement the same interface (Animal) without further specification (active Profiles, or #Primary annotation) Spring won't be able to decide which implementation to inject while creating the MyTestController,
What you want to do is return beans from your ApplicationContext based on a parameter / class name. This would look something like this:
#Autowired
private ApplicationContext context;
/* ... */
if(animalName.equals("dog") {
context.getBean(Dog.class) //returning the dog bean
} else if(animalName.equals("cat") {
context.getBean(Cat.class) //returning the cat bean
}
Edit IMO the question is a bit confusing. You ask for wiring the bean based on a value, but this value only comes at runtime. Hence my answer. However If you want to wire based on some variable at initialisation of your bean I would suggest taking a look at the following sources:
Profiles - With profiles you can tell spring which instance to inject in which configuration. (E.g.: production/development/test configs and for each you want to inject different beans)
Primary - One of your bean takes precedence over the others while injecting it.
Qualifier
Finally I would note that such an inversion on the IoC is considered as a bad practice. (See here)
Well, you're missing the whole point. Don't autowire simple DTO, but autowire AnimalFactory or some kind of AnimalRepository (or better - Service) where you can create or retrieve animals based on animal type.
It would look something like that:
#Component
public class AnimalFactory {
public Animal createAnimal(String animalType) {
switch (animalType) {
case "DOG":
return new Dog();
case "CAT":
return new Cat();
}
throw new IllegalArgumentException("AnimalType is invalid");
}
}
Animal Spring Data JPA Repository:
#Component
public class AnimalRepository implements JpaRepository<Animal, Long> {
public Optional<Animal> findByAnimalName(String animalName);
}

When autowiring use would be beneficiary with example

I have recently learned concept of autowiring in spring. When I was trying to understand in which particular scenarios spring autowiring can be useful
I came up with the below two reasons from one of the questions asked in our stakoverflow forum.
1.I wanted to read values from a property file and inject them into a bean. Only way I could figure out how to do this at start up of my app was to
wire the bean in XML (and inject the properties.) I ended up using the "byName" attribute (because the bean was also marked as #Component) and then
used #Autowired #Qualifier("nameIChose") when injecting the bean into another class. It's the only bean I've written that I wire with XML.
2.I've found autowiring useful in cases where I've had a factory bean making another bean (whose implementation class name was described in a system
property,so I couldn't define the all wiring in XML). I usually prefer to make my wiring explicit though;
Can any body please give me some code snippet example of the above situations that would make my understanding of autowiring more clearer?
Here is an example of injecting properties into a bean.
Using field injection:
#Component
public class YourBean {
#Value("${your.property.name}")
private String yourProperty;
}
Using constructor injection:
#Component
public class YourBean2 {
private String yourProperty;
#Autowired
public YourBeans2(#Value("${your.property.name}") String yourProperty) {
this.yourProperty = yourProperty;
}
}
The following is a super simple example of autowiring various beans
#Component
public class Foo {
public void doSomething() {
}
}
#Component
public class Bar {
private Foo foo;
#Autowired
public Bar(Foo foo) {
this.foo = foo;
}
public void doSomethingElse() {
foo.doSomething();
}
}
In the previous example, no XML configuration of Foo and Bar needs to be done, Spring automatically picks up the beans because of their #Component annotation (assuming of course that component scanning has been enabled)

Resources