@Lookup Annotatie in het voorjaar

1. Inleiding

In deze korte tutorial kijken we naar Spring's methode-niveau afhankelijkheid injectie ondersteuning, via de @Opzoeken annotatie.

2. Waarom @Opzoeken?

Een methode geannoteerd met @Opzoeken vertelt Spring om een ​​instantie van het retourtype van de methode te retourneren wanneer we het aanroepen.

In wezen zal Spring onze geannoteerde methode overschrijven en het retourtype en de parameters van onze methode gebruiken als argumenten voor BeanFactory # getBean.

@Opzoeken is handig voor:

  • Het injecteren van een boon met prototypebereik in een singletonboon (vergelijkbaar met Aanbieder)
  • Afhankelijkheden procedureel injecteren

Merk ook op dat @Opzoeken is het Java-equivalent van het XML-element lookup-methode.

3. Met behulp van @Opzoeken

3.1. Het injecteren van een prototype-scoped Bean in een Singleton Bean

Als we besluiten om een ​​prototype van een springboon te hebben, worden we vrijwel onmiddellijk geconfronteerd met het probleem: hoe krijgen onze singleton springbonen toegang tot deze prototype springbonen?

Nu, Aanbieder is echter zeker een manier @Opzoeken is in sommige opzichten veelzijdiger.

Laten we eerst een prototype bean maken die we later in een singleton bean zullen injecteren:

@Component @Scope ("prototype") openbare klas SchoolNotification {// ... prototype-scoped state}

En als we een singletonboon maken die gebruikmaakt van @Opzoeken:

@Component openbare klas StudentServices {// ... lidvariabelen, enz. @Lookup openbare SchoolNotification getNotification () {return null; } // ... getters en setters}

Gebruik makend van @Opzoeken, kunnen we een exemplaar krijgen van Kennisgeving van de school via onze singleton boon:

@Test openbare void whenLookupMethodCalled_thenNewInstanceReturned () {// ... initialiseer eerst context StudentServices = this.context.getBean (StudentServices.class); StudentServices second = this.context.getBean (StudentServices.class); assertEquals (eerste, tweede); assertNotEquals (first.getNotification (), second.getNotification ()); }

Merk op dat in StudentServices, we verlieten de melding krijgen methode als een stomp.

Dit komt doordat Spring de methode overschrijft met een aanroep naar beanFactory.getBean (StudentNotification.class), zodat we het leeg kunnen laten.

3.2. Procedureel afhankelijkheden injecteren

Maar nog krachtiger is dat @Opzoeken stelt ons in staat om procedureel een afhankelijkheid te injecteren, iets waar we niet mee kunnen doen Aanbieder.

Laten we verbeteren Kennisgeving van de student met een bepaalde staat:

@Component @Scope ("prototype") openbare klas SchoolNotification {@Autowired Grader grader; private String naam; merken voor privécollecties; public SchoolNotification (String naam) {// ... set velden} // ... getters en setters public String addMark (geheel getal) {this.marks.add (mark); retourneer this.grader.grade (this.marks); }}

Nu is het afhankelijk van een bepaalde lente-context en ook van aanvullende context die we procedureel zullen bieden.

We kunnen dan een methode toevoegen aan StudentServices die studentgegevens gebruikt en deze vasthoudt:

openbare abstracte klasse StudentServices {privékaartnotities = nieuwe HashMap (); @Lookup beschermde abstracte SchoolNotification getNotification (String naam); public String appendMark (Stringnaam, geheel getal) {SchoolNotification-melding = notes.computeIfAbsent (naam, bestaat -> getNotification (naam))); retourmelding.addMark (markeren); }} 

Tijdens runtime zal Spring de methode op dezelfde manier implementeren, met een paar extra trucs.

Merk allereerst op dat het een complexe constructor kan bellen en ook andere Spring beans kan injecteren, waardoor we kunnen behandelen Kennisgeving van de school een beetje meer als een lentebewuste methode.

Het doet dit door te implementeren getSchoolNotification met een oproep naar beanFactory.getBean (SchoolNotification.class, naam).

Ten tweede kunnen we soms de @Opzoeken-geannoteerde methode abstract, zoals het bovenstaande voorbeeld.

Gebruik makend van abstract ziet er een beetje mooier uit dan een stomp, maar we kunnen het alleen gebruiken als we niet doencomponent-scan of @Boon-beheer de omringende boon:

@Test openbare void whenAbstractGetterMethodInjects_thenNewInstanceReturned () {// ... initialiseer context StudentServices services = context.getBean (StudentServices.class); assertEquals ("PASS", services.appendMark ("Alex", 89)); assertEquals ("FAIL", services.appendMark ("Bethany", 78)); assertEquals ("PASS", services.appendMark ("Claire", 96)); }

Met deze setup kunnen we zowel Spring-afhankelijkheden als methode-afhankelijkheden toevoegen aan Kennisgeving van de school.

4. Beperkingen

Ondanks @Opzoeken‘S veelzijdigheid, zijn er een paar opmerkelijke beperkingen:

  • @Opzoeken-geannoteerde methoden, zoals melding krijgen, moet concreet zijn als de omringende klas, zoals Leerling, is component-gescand. Dit komt doordat bij het scannen van componenten abstracte bonen worden overgeslagen.
  • @Opzoeken-geannoteerde methoden zullen helemaal niet werken als de omringende klasse dat wel is @Boon-beheerd.

Als we in die omstandigheden een prototype boon in een singleton moeten injecteren, kunnen we kijken naar Aanbieder als een alternatief.

5. Conclusie

In dit korte artikel hebben we geleerd hoe en wanneer we Spring's moeten gebruiken @Opzoeken annotatie, inclusief hoe het te gebruiken om bonen met prototype scoped in singleton beans te injecteren en hoe het te gebruiken om procedureel afhankelijkheden te injecteren.

Alle code die voor deze tutorial wordt gebruikt, is te vinden op Github.