In my example here, I have a "Hero" bean which can be injected with a "Weapon" bean. Both Heros and Weapons are prototype-scoped (we can have multiple heroes, and they won't share weapons).
What I want to have is a Hero configuration called "Warrior" which is injected with a "Sword" weapon, and a Hero configuration called "Archer" which is injected with a "Bow" weapon. Then in my application I would call
context.getBean("Warrior");
each time I want to get a new warrior.
I know how to do this with XML, but I was wondering if it is possible to do this with annotations? If so, how do I do it? I am using Spring 4.
Example of LuiggiMendoza's comment (autowiring and qualifying the setter)
Sticking to the script of programming to interfaces, we have the Hero interface
public interface Hero {
void killOrBeKilled();
}
We'll also have an AbstractHero abstract class to put together some common functionality. Notice we don't implement the setWeapon method. We'll leave that to the concrete class.
public abstract class AbstractHero implements Hero {
protected Weapon weapon;
public void killOrBeKilled() {
weapon.secretWeaponManeuver();
}
protected abstract void setWeapon(Weapon weapon);
}
And here are the Qualifiers we'll use. Note, you don't have to create your own qualifiers. You could simply use @Qualifer("qualifierName") for your matchings. I did it just because I could :P
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE})
public @interface BowType { }
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE})
public @interface SwordType { }
For the Warrior we'll use the @SwordType qualifier
@Component
public class Warrior extends AbstractHero {
@SwordType
@Autowired
public void setWeapon(Weapon weapon) {
this.weapon = weapon;
}
}
And for the Archer we'll use the @BowType qualifier
@Component
public class Archer extends AbstractHero {
@BowType
@Autowired
public void setWeapon(Weapon weapon) {
this.weapon = weapon;
}
}
In our Weapons concrete classes, we'll also need to annotate the classes with the appropriate qualifiers
public interface Weapon {
void secretWeaponManeuver();
}
@BowType
@Component
public class Bow implements Weapon {
public void secretWeaponManeuver() {
System.out.println("Bow goes Slinnnggggg!");
}
}
@SwordType
@Component
public class Sword implements Weapon {
public void secretWeaponManeuver() {
System.out.println("Sword goes Slassshhhh!");
}
}
When we run the application, the weapon types will be injected properly based on our qualifiers
@Configuration
@ComponentScan(basePackages = {"com.stackoverflow.spring.hero"})
public class Config { }
public class Application {
public static void main(String[] args) {
AbstractApplicationContext context =
new AnnotationConfigApplicationContext(Config.class);
Hero warrior = context.getBean(Warrior.class);
warrior.killOrBeKilled();
Hero archer = context.getBean(Archer.class);
archer.killOrBeKilled();
context.close();
}
}
Result
Sword goes Slassshhhh!
Bow goes Slinnnggggg!
P.S. I forgot the @Scope("prototype") annotation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With