Anotaciones de Spring Core

Este artículo es parte de una serie: • Spring Core Annotations (artículo actual) • Spring Web Annotations

• Anotaciones de Spring Boot

• Anotaciones de programación de primavera

• Anotaciones de datos de primavera

• Anotaciones de Spring Bean

1. Información general

Podemos aprovechar las capacidades del motor Spring DI usando las anotaciones en los paquetes org.springframework.beans.factory.annotation y org.springframework.context.annotation .

A menudo las llamamos "anotaciones principales de Spring" y las revisaremos en este tutorial.

2. Anotaciones relacionadas con DI

2.1. @Autowired

Podemos usar @Autowired para marcar una dependencia que Spring va a resolver e inyectar . Podemos usar esta anotación con un constructor, definidor o inyección de campo.

Inyección de constructor:

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

Inyección de setter:

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

Inyección de campo:

class Car { @Autowired Engine engine; }

@Autowired tiene un argumento booleano llamado required con un valor predeterminado de verdadero . Ajusta el comportamiento de Spring cuando no encuentra un bean adecuado para conectar. Cuando es verdadero , se lanza una excepción; de lo contrario, no se conecta nada.

Tenga en cuenta que si usamos la inyección del constructor, todos los argumentos del constructor son obligatorios.

A partir de la versión 4.3, no necesitamos anotar los constructores con @Autowired explícitamente a menos que declaremos al menos dos constructores.

Para obtener más detalles, visite nuestros artículos sobre @Autowired y la inyección de constructores.

2.2. @Frijol

@Bean marca un método de fábrica que crea una instancia de un bean Spring:

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

Spring llama a estos métodos cuando se requiere una nueva instancia del tipo de retorno.

El bean resultante tiene el mismo nombre que el método de fábrica. Si queremos nombrarlo de otra manera, podemos hacerlo con el nombre o los argumentos de valor de esta anotación (el valor del argumento es un alias para el nombre del argumento ):

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

Tenga en cuenta que todos los métodos anotados con @Bean deben estar en las clases @Configuration .

2.3. @Calificatorio

Usamos @Qualifier junto con @Autowired para proporcionar la identificación del bean o el nombre del bean que queremos usar en situaciones ambiguas.

Por ejemplo, los siguientes dos beans implementan la misma interfaz:

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

Si Spring necesita inyectar un bean de vehículo , termina con múltiples definiciones coincidentes. En tales casos, podemos proporcionar el nombre de un bean explícitamente usando la anotación @Qualifier .

Usando inyección de constructor:

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

Usando inyección de incubadora:

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

Alternativamente:

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

Usando inyección de campo:

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

Para obtener una descripción más detallada, lea este artículo.

2.4. @Necesario

@Required en los métodos de establecimiento para marcar las dependencias que queremos completar a través de XML:

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

De lo contrario, se lanzará BeanInitializationException .

2.5. @Valor

Podemos usar @Value para inyectar valores de propiedad en beans. Es compatible con constructor, setter e inyección de campo.

Inyección de constructor:

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

Inyección de setter:

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

Alternativamente:

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

Inyección de campo:

@Value("8") int cylinderCount;

Por supuesto, inyectar valores estáticos no es útil. Por lo tanto, podemos usar cadenas de marcadores de posición en @Value para conectar valores definidos en fuentes externas , por ejemplo, en archivos .properties o .yaml .

Supongamos el siguiente archivo .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 aprovecha la función de anotaciones repetidas de Java 8, lo que significa que podemos marcar una clase con ella varias veces:

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

3.5. @PropertySources

Podemos usar esta anotación para especificar múltiples configuraciones de @PropertySource :

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

Tenga en cuenta que desde Java 8 podemos lograr lo mismo con la función de anotaciones repetidas descrita anteriormente.

4. Conclusión

En este artículo, vimos una descripción general de las anotaciones principales de Spring más comunes. Vimos cómo configurar el cableado del bean y el contexto de la aplicación, y cómo marcar clases para el escaneo de componentes.

Como de costumbre, los ejemplos están disponibles en GitHub.

Siguiente » Spring Web Annotations