Constructor afhankelijkheidsinjectie in het voorjaar

1. Inleiding

Een van de belangrijkste ontwikkelingsprincipes van modern softwareontwerp is ongetwijfeld Afhankelijkheidsinjectie (DI) die heel natuurlijk voortvloeit uit een ander kritisch belangrijk principe: Modulariteit.

Dit artikel gaat in op een specifiek type DI-techniek genaamd Op constructeurs gebaseerde afhankelijkheidsinjectie binnen Spring - wat simpel gezegd betekent dat vereiste componenten op het moment van instantiatie in een klasse worden doorgegeven.

Om te beginnen moeten we importeren lente-context afhankelijkheid in onze pom.xml:

 org.springframework spring-context 5.2.8.RELEASE 

Dan moeten we een Configuratie het dossier. Dit bestand kan een POJO zijn of, indien gewenst, een XML-bestand.

2. Op aantekeningen gebaseerde configuratie

Java-configuratiebestand lijkt veel op een gewoon oud Java-object met enkele aanvullende annotaties:

@Configuration @ComponentScan ("com.baeldung.constructordi") publieke klasse Config {@Bean public Engine engine () {retourneer nieuwe Engine ("v8", 5); } @Bean openbare transmissie transmissie () {nieuwe transmissie teruggeven ("glijdend"); }} 

Hier gebruiken we annotaties om Spring runtime te laten weten dat deze klasse een leverancier is van bean-definities (@Boon annotatie) en dat een contextscan voor extra bonen in het pakket moet worden uitgevoerd com.baeldung.spring. Vervolgens definiëren we een Auto klasse:

@Component openbare auto {@Autowired openbare auto (motormotor, transmissietransmissie) {this.engine = engine; this.transmission = verzending; }}

De lente zal onze tegenkomen Auto class tijdens het uitvoeren van een pakketscan en zal de instantie initialiseren door de @Autowired geannoteerde constructor.

Instanties van Motor en transmissie wordt verkregen door te bellen @Boon geannoteerde methoden van de Config klasse. Ten slotte moeten we een ApplicationContext met behulp van onze POJO-configuratie:

ApplicationContext context = nieuwe AnnotationConfigApplicationContext (Config.class); Auto auto = context.getBean (Car.class);

3. Impliciete constructorinjectie

Vanaf Spring 4.3 kunnen klassen met een enkele constructor de @Autowired annotatie. Een leuk klein beetje gemak en het verwijderen van de boilerplate!

Bovendien kan, ook te beginnen met 4.3, de constructor-gebaseerde injectie worden gebruikt in @Configuratie geannoteerde klassen. En ja, als zo'n klasse maar één constructor heeft, is de @Autowired annotatie kan ook worden weggelaten.

4. XML-gebaseerde configuratie

Een andere manier om Spring-runtime te configureren met op constructor gebaseerde afhankelijkheidsinjectie, is door een XML-configuratiebestand te gebruiken:

Let daar op constructor-arg kan een letterlijke waarde of een verwijzing naar een andere bean accepteren en dat is een optionele expliciete inhoudsopgave en type kan worden geleverd. Type en inhoudsopgave attributen kunnen worden gebruikt om ambiguïteit op te lossen (bijvoorbeeld als een constructor meerdere argumenten van hetzelfde type accepteert).

naam attribuut kan ook worden gebruikt voor het matchen van xml naar java-variabelen, maar dan uw code moet worden gecompileerd met de foutopsporingsvlag aan.

Een Spring-toepassingscontext moet in dit geval worden opgestart met ClassPathXmlApplicationContext:

ApplicationContext context = nieuwe ClassPathXmlApplicationContext ("baeldung.xml"); Auto auto = context.getBean (Car.class);

5. Voors en tegens

Constructorinjectie heeft een aantal voordelen ten opzichte van veldinjectie.

Het eerste voordeel is testbaarheid. Stel dat we een springboon gaan testen die veldinjectie gebruikt:

openbare klasse UserService {@Autowired privé UserRepository userRepository; }

Tijdens de bouw van een Gebruikersservice we kunnen de userRepository staat. De enige manier om dit te bereiken is via de Reflection API, die de inkapseling volledig verbreekt. De resulterende code is ook minder veilig in vergelijking met een eenvoudige constructor-aanroep.

Bovendien, metveldinjectie, kunnen we invarianten op klassenniveau niet afdwingen.Het is dus mogelijk om een Gebruikersservice instantie zonder een correct geïnitialiseerd userRepository. Daarom kunnen we willekeurig ervaren NullPointerExceptions hier en daar. Met constructor-injectie is het ook gemakkelijker om onveranderlijke componenten te bouwen.

Bovendien, het gebruik van constructors om objectinstanties te maken is natuurlijker vanuit het oogpunt van OOP.

Aan de andere kant is het grootste nadeel van constructor-injectie de breedsprakigheid, vooral wanneer een boon een handvol afhankelijkheden heeft. Soms kan het een vermomde zegen zijn, omdat we misschien harder proberen om het aantal afhankelijkheden zo klein mogelijk te houden.

6. Conclusie

Deze korte tutorial heeft de basis getoond van twee verschillende manieren om te gebruiken Op constructeurs gebaseerde afhankelijkheidsinjectie met behulp van het Spring-raamwerk.

De volledige implementatie van deze tutorial is te vinden op GitHub.