Annotazioni Spring Core

Questo articolo fa parte di una serie: • Spring Core Annotations (articolo corrente) • Spring Web Annotations

• Annotazioni Spring Boot

• Annotazioni di pianificazione della primavera

• Annotazioni sui dati primaverili

• Annotazioni Spring Bean

1. Panoramica

Possiamo sfruttare le capacità del motore DI Spring utilizzando le annotazioni nei pacchetti org.springframework.beans.factory.annotation e org.springframework.context.annotation .

Spesso chiamiamo queste "annotazioni principali di Spring" e le esamineremo in questo tutorial.

2. Annotazioni relative a DI

2.1. @Autowired

Possiamo usare @Autowired per contrassegnare una dipendenza che Spring risolverà e inserirà . Possiamo usare questa annotazione con un costruttore, setter o field injection.

Iniezione nel costruttore:

class Car { Engine engine; @Autowired Car(Engine engine) { this.engine = engine; } }

Iniezione di setter:

class Car { Engine engine; @Autowired void setEngine(Engine engine) { this.engine = engine; } }

Iniezione sul campo:

class Car { @Autowired Engine engine; }

@Autowired ha un argomento booleano chiamato richiesto con un valore predefinito di true . Regola il comportamento di Spring quando non trova un fagiolo adatto da cablare. Quando è vero , viene lanciata un'eccezione, altrimenti non viene cablato nulla.

Nota che se usiamo l'iniezione del costruttore, tutti gli argomenti del costruttore sono obbligatori.

A partire dalla versione 4.3, non abbiamo bisogno di annotare esplicitamente i costruttori con @Autowired a meno che non dichiariamo almeno due costruttori.

Per maggiori dettagli, visita i nostri articoli su @Autowired e l'iniezione nel costruttore.

2.2. @Fagiolo

@Bean contrassegna un metodo factory che istanzia un bean Spring:

@Bean Engine engine() { return new Engine(); }

Spring chiama questi metodi quando è richiesta una nuova istanza del tipo restituito.

Il bean risultante ha lo stesso nome del metodo factory. Se vogliamo nominarlo in modo diverso, possiamo farlo con il nome o gli argomenti del valore di questa annotazione (il valore dell'argomento è un alias per il nome dell'argomento ):

@Bean("engine") Engine getEngine() { return new Engine(); }

Nota che tutti i metodi annotati con @Bean devono essere nelle classi @Configuration .

2.3. @Qualifier

Usiamo @Qualifier insieme a @Autowired per fornire l'id o il nome del bean che vogliamo utilizzare in situazioni ambigue.

Ad esempio, i seguenti due bean implementano la stessa interfaccia:

class Bike implements Vehicle {} class Car implements Vehicle {}

Se Spring ha bisogno di iniettare un bean Vehicle , finisce con più definizioni corrispondenti. In questi casi, possiamo fornire il nome di un bean esplicitamente utilizzando l' annotazione @Qualifier .

Utilizzando l'iniezione nel costruttore:

@Autowired Biker(@Qualifier("bike") Vehicle vehicle) { this.vehicle = vehicle; }

Utilizzando l'iniezione di setter:

@Autowired void setVehicle(@Qualifier("bike") Vehicle vehicle) { this.vehicle = vehicle; }

In alternativa:

@Autowired @Qualifier("bike") void setVehicle(Vehicle vehicle) { this.vehicle = vehicle; }

Utilizzando l'iniezione di campo:

@Autowired @Qualifier("bike") Vehicle vehicle;

Per una descrizione più dettagliata, leggi questo articolo.

2.4. @Necessario

@ Richiesto sui metodi setter per contrassegnare le dipendenze che vogliamo popolare tramite XML:

@Required void setColor(String color) { this.color = color; }

In caso contrario, verrà generata BeanInitializationException .

2.5. @Valore

Possiamo usare @Value per iniettare valori di proprietà nei bean. È compatibile con costruttore, setter e field injection.

Iniezione nel costruttore:

Engine(@Value("8") int cylinderCount) { this.cylinderCount = cylinderCount; }

Iniezione di setter:

@Autowired void setCylinderCount(@Value("8") int cylinderCount) { this.cylinderCount = cylinderCount; }

In alternativa:

@Value("8") void setCylinderCount(int cylinderCount) { this.cylinderCount = cylinderCount; }

Iniezione sul campo:

@Value("8") int cylinderCount;

Ovviamente, l'iniezione di valori statici non è utile. Pertanto, possiamo utilizzare stringhe segnaposto in @Value per collegare i valori definiti in sorgenti esterne , ad esempio, nei file .properties o .yaml .

Supponiamo il seguente file .properties :

engine.fuelType=petrol

We can inject the value of engine.fuelType with the following:

@Value("${engine.fuelType}") String fuelType;

We can use @Value even with SpEL. More advanced examples can be found in our article about @Value.

2.6. @DependsOn

We can use this annotation to make Spring initialize other beans before the annotated one. Usually, this behavior is automatic, based on the explicit dependencies between beans.

We only need this annotation when the dependencies are implicit, for example, JDBC driver loading or static variable initialization.

We can use @DependsOn on the dependent class specifying the names of the dependency beans. The annotation's value argument needs an array containing the dependency bean names:

@DependsOn("engine") class Car implements Vehicle {}

Alternatively, if we define a bean with the @Bean annotation, the factory method should be annotated with @DependsOn:

@Bean @DependsOn("fuel") Engine engine() { return new Engine(); }

2.7. @Lazy

We use @Lazy when we want to initialize our bean lazily. By default, Spring creates all singleton beans eagerly at the startup/bootstrapping of the application context.

However, there are cases when we need to create a bean when we request it, not at application startup.

This annotation behaves differently depending on where we exactly place it. We can put it on:

  • a @Bean annotated bean factory method, to delay the method call (hence the bean creation)
  • a @Configuration class and all contained @Bean methods will be affected
  • a @Component class, which is not a @Configuration class, this bean will be initialized lazily
  • an @Autowired constructor, setter, or field, to load the dependency itself lazily (via proxy)

This annotation has an argument named value with the default value of true. It is useful to override the default behavior.

For example, marking beans to be eagerly loaded when the global setting is lazy, or configure specific @Bean methods to eager loading in a @Configuration class marked with @Lazy:

@Configuration @Lazy class VehicleFactoryConfig { @Bean @Lazy(false) Engine engine() { return new Engine(); } }

For further reading, please visit this article.

2.8. @Lookup

A method annotated with @Lookup tells Spring to return an instance of the method’s return type when we invoke it.

Detailed information about the annotation can be found in this article.

2.9. @Primary

Sometimes we need to define multiple beans of the same type. In these cases, the injection will be unsuccessful because Spring has no clue which bean we need.

We already saw an option to deal with this scenario: marking all the wiring points with @Qualifier and specify the name of the required bean.

However, most of the time we need a specific bean and rarely the others. We can use @Primary to simplify this case: if we mark the most frequently used bean with @Primary it will be chosen on unqualified injection points:

@Component @Primary class Car implements Vehicle {} @Component class Bike implements Vehicle {} @Component class Driver { @Autowired Vehicle vehicle; } @Component class Biker { @Autowired @Qualifier("bike") Vehicle vehicle; }

In the previous example Car is the primary vehicle. Therefore, in the Driver class, Spring injects a Car bean. Of course, in the Biker bean, the value of the field vehicle will be a Bike object because it's qualified.

2.10. @Scope

We use @Scope to define the scope of a @Component class or a @Bean definition. It can be either singleton, prototype, request, session, globalSession or some custom scope.

For example:

@Component @Scope("prototype") class Engine {}

3. Context Configuration Annotations

We can configure the application context with the annotations described in this section.

3.1. @Profile

If we want Spring to use a @Component class or a @Bean method only when a specific profile is active, we can mark it with @Profile. We can configure the name of the profile with the value argument of the annotation:

@Component @Profile("sportDay") class Bike implements Vehicle {}

You can read more about profiles in this article.

3.2. @Import

We can use specific @Configuration classes without component scanning with this annotation. We can provide those classes with @Import‘s value argument:

@Import(VehiclePartSupplier.class) class VehicleFactoryConfig {}

3.3. @ImportResource

We can import XML configurations with this annotation. We can specify the XML file locations with the locations argument, or with its alias, the value argument:

@Configuration @ImportResource("classpath:/annotations.xml") class VehicleFactoryConfig {}

3.4. @PropertySource

With this annotation, we can define property files for application settings:

@Configuration @PropertySource("classpath:/annotations.properties") class VehicleFactoryConfig {}

@PropertySource sfrutta la funzionalità di annotazioni ripetute di Java 8, il che significa che possiamo contrassegnare una classe con essa più volte:

@Configuration @PropertySource("classpath:/annotations.properties") @PropertySource("classpath:/vehicle-factory.properties") class VehicleFactoryConfig {}

3.5. @PropertySources

Possiamo usare questa annotazione per specificare più configurazioni @PropertySource :

@Configuration @PropertySources({ @PropertySource("classpath:/annotations.properties"), @PropertySource("classpath:/vehicle-factory.properties") }) class VehicleFactoryConfig {}

Nota che a partire da Java 8 possiamo ottenere lo stesso risultato con la funzione di annotazioni ripetute come descritto sopra.

4. Conclusione

In questo articolo, abbiamo visto una panoramica delle annotazioni principali di Spring più comuni. Abbiamo visto come configurare il cablaggio dei bean e il contesto dell'applicazione e come contrassegnare le classi per la scansione dei componenti.

Come al solito, gli esempi sono disponibili su GitHub.

Avanti » Annotazioni Web di primavera