Anotações do núcleo da mola
1. Visão geral
Podemos aproveitar os recursos do mecanismo Spring DI usando as anotações nos pacotesorg.springframework.beans.factory.annotation andorg.springframework.context.annotation.
Frequentemente chamamos isso de “anotações do Spring core” e iremos analisá-las neste tutorial.
2. Anotações relacionadas a DI
2.1. @Autowired
Podemos usar@Autowired amark a dependency which Spring is going to resolve and inject. Podemos usar esta anotação com um construtor, setter ou injeção de campo.
Injeção de construtor:
class Car {
Engine engine;
@Autowired
Car(Engine engine) {
this.engine = engine;
}
}
Injeção de incubadora:
class Car {
Engine engine;
@Autowired
void setEngine(Engine engine) {
this.engine = engine;
}
}
Injeção em campo:
class Car {
@Autowired
Engine engine;
}
@Autowired tem um argumentoboolean chamadorequired com um valor padrão detrue. Ele ajusta o comportamento do Spring quando não encontra um bean adequado para conectar. Quandotrue, uma exceção é lançada, caso contrário, nada é conectado.
Observe que, se usarmos injeção de construtor, todos os argumentos do construtor serão obrigatórios.
A partir da versão 4.3, não precisamos anotar construtores com@Autowired explicitamente, a menos que declaremos pelo menos dois construtores.
Para obter mais detalhes, visite nossos artigos sobre@Autowiredeconstructor injection.
2.2. @Bean
@Bean marca um método de fábrica que instancia um bean Spring:
@Bean
Engine engine() {
return new Engine();
}
Spring calls these methods quando uma nova instância do tipo de retorno é necessária.
O bean resultante tem o mesmo nome que o método de fábrica. Se quisermos nomeá-lo de forma diferente, podemos fazer isso com os argumentosname ouvalue desta anotação (o argumentovalue é um apelido para o argumentoname) :
@Bean("engine")
Engine getEngine() {
return new Engine();
}
Observe que todos os métodos anotados com@Bean devem estar nas classes@Configuration.
2.3. @Qualifier
Usamos@Qualifier junto com@Autowired paraprovide the bean id or bean name que queremos usar em situações ambíguas.
Por exemplo, os dois beans a seguir implementam a mesma interface:
class Bike implements Vehicle {}
class Car implements Vehicle {}
Se o Spring precisar injetar um beanVehicle, ele terminará com várias definições correspondentes. Nesses casos, podemos fornecer o nome de um bean explicitamente usando a anotação@Qualifier.
Usando injeção de construtor:
@Autowired
Biker(@Qualifier("bike") Vehicle vehicle) {
this.vehicle = vehicle;
}
Usando injeção setter:
@Autowired
void setVehicle(@Qualifier("bike") Vehicle vehicle) {
this.vehicle = vehicle;
}
Alternativamente:
@Autowired
@Qualifier("bike")
void setVehicle(Vehicle vehicle) {
this.vehicle = vehicle;
}
Usando injeção de campo:
@Autowired
@Qualifier("bike")
Vehicle vehicle;
Para uma descrição mais detalhada, leiathis article.
2.4. @Required
@Required em métodos setter para marcar dependências que desejamos preencher por meio de XML:
@Required
void setColor(String color) {
this.color = color;
}
Caso contrário,BeanInitializationException será lançado.
2.5. @Value
Podemos usar@Value para injetar valores de propriedade nos beans. É compatível com construtor, setter e injeção de campo.
Injeção de construtor:
Engine(@Value("8") int cylinderCount) {
this.cylinderCount = cylinderCount;
}
Injeção de incubadora:
@Autowired
void setCylinderCount(@Value("8") int cylinderCount) {
this.cylinderCount = cylinderCount;
}
Alternativamente:
@Value("8")
void setCylinderCount(int cylinderCount) {
this.cylinderCount = cylinderCount;
}
Injeção em campo:
@Value("8")
int cylinderCount;
Claro, injetar valores estáticos não é útil. Portanto, podemos usarplaceholder strings em@Value para conectar valoresdefined in external sources, por exemplo, em arquivos.properties ou.yaml.
Vamos supor o seguinte arquivo.properties:
engine.fuelType=petrol
Podemos injetar o valor deengine.fuelType com o seguinte:
@Value("${engine.fuelType}")
String fuelType;
Podemos usar@Value mesmo com SpEL. Exemplos mais avançados podem ser encontrados em nossoarticle about @Value.
2.6. @DependsOn
Podemos usar essa anotação para fazer Springinitialize other beans before the annotated one. Geralmente, esse comportamento é automático, com base nas dependências explícitas entre os beans.
Precisamos apenas dessa anotaçãowhen the dependencies are implicit, por exemplo, carregamento do driver JDBC ou inicialização de variável estática.
Podemos usar@DependsOn na classe dependente especificando os nomes dos beans de dependência. O argumentovalue da anotação precisa de uma matriz contendo os nomes do bean de dependência:
@DependsOn("engine")
class Car implements Vehicle {}
Alternativamente, se definirmos um bean com a anotação@Bean, o método de fábrica deve ser anotado com@DependsOn:
@Bean
@DependsOn("fuel")
Engine engine() {
return new Engine();
}
2.7. @Lazy
Usamos@Lazy quando queremos inicializar nosso bean preguiçosamente. Por padrão, o Spring cria todos os beans singleton ansiosamente na inicialização / inicialização do contexto do aplicativo.
Porém, há casos em quewe need to create a bean when we request it, not at application startup.
Essa anotação se comporta de maneira diferente, dependendo de onde a colocamos exatamente. Podemos colocar:
-
um método de fábrica de bean anotado@Bean, para atrasar a chamada do método (daí a criação do bean)
-
uma classe @Configuration e todos os métodos@Bean contidos serão afetados
-
uma classe@Component, que não é uma classe@Configuration, este bean será inicializado lentamente
-
um construtor, setter ou campo@Autowired para carregar a própria dependência lentamente (via proxy)
Esta anotação possui um argumento denominadovalue com o valor padrão detrue. É útil substituir o comportamento padrão.
Por exemplo, marcar os beans para serem carregados antecipadamente quando a configuração global for lenta ou configurar métodos@Bean específicos para carregamento antecipado em uma classe@Configuration marcada com@Lazy:
@Configuration
@Lazy
class VehicleFactoryConfig {
@Bean
@Lazy(false)
Engine engine() {
return new Engine();
}
}
Para ler mais, visitethis article.
2.8. @Lookup
Um método anotado com@Lookup diz ao Spring para retornar uma instância do tipo de retorno do método quando o invocarmos.
Informações detalhadas sobre a anotaçãocan be found in this article.
2.9. @Primary
Às vezes, precisamos definir vários beans do mesmo tipo. Nesses casos, a injeção não terá êxito porque o Spring não tem idéia de qual feijão precisamos.
Já vimos uma opção para lidar com este cenário: marcar todos os pontos de fiação com@Qualifiere especificar o nome do bean necessário.
No entanto, na maioria das vezes precisamos de um bean específico e raramente dos outros. Podemos usar@Primary para simplificar este caso: sewe mark the most frequently used bean with @Primary, será escolhido em pontos de injeção não qualificados:
@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;
}
No exemplo anterior,Car é o veículo principal. Portanto, na classeDriver, o Spring injeta um beanCar. Claro, no beanBiker, o valor do campovehicle será um objetoBike porque é qualificado.
2.10. @Scope
Usamos@Scope para definir oscope de uma classe@Component ou uma definição@Bean.. Pode sersingleton, prototype, request, session, globalSession ou algum escopo personalizado.
Por exemplo:
@Component
@Scope("prototype")
class Engine {}
3. Anotações de configuração de contexto
Podemos configurar o contexto do aplicativo com as anotações descritas nesta seção.
3.1. @Profile
Se quisermos que o Spring sejause a @Component class or a @Bean method only when a specific profile is active, podemos marcá-lo com@Profile. Podemos configurar o nome do perfil com o argumentovalue da anotação:
@Component
@Profile("sportDay")
class Bike implements Vehicle {}
Você pode ler mais sobre perfis emthis article.
3.2. @Import
Podemos usarspecific @Configuration classes without component scanning com esta anotação. Podemos fornecer a essas classes o argumento@Import'svalue:
@Import(VehiclePartSupplier.class)
class VehicleFactoryConfig {}
3.3. @ImportResource
Podemosimport XML configurations com esta anotação. Podemos especificar os locais do arquivo XML com o argumentolocations, ou com seu alias, o argumentovalue:
@Configuration
@ImportResource("classpath:/annotations.xml")
class VehicleFactoryConfig {}
3.4. @PropertySource
Com esta anotação, podemosdefine property files for application settings:
@Configuration
@PropertySource("classpath:/annotations.properties")
class VehicleFactoryConfig {}
@PropertySource aproveita o recurso de anotações repetidas do Java 8, o que significa que podemos marcar uma classe com ele várias vezes:
@Configuration
@PropertySource("classpath:/annotations.properties")
@PropertySource("classpath:/vehicle-factory.properties")
class VehicleFactoryConfig {}
3.5. @PropertySources
Podemos usar esta anotação para especificar várias configurações de@PropertySource:
@Configuration
@PropertySources({
@PropertySource("classpath:/annotations.properties"),
@PropertySource("classpath:/vehicle-factory.properties")
})
class VehicleFactoryConfig {}
Observe que, desde o Java 8, podemos obter o mesmo com o recurso de anotações repetidas, conforme descrito acima.
4. Conclusão
Neste artigo, vimos uma visão geral das anotações principais do Spring mais comuns. Vimos como configurar a fiação do bean e o contexto do aplicativo e como marcar as classes para a varredura de componentes.
Como de costume, os exemplos estão disponíveisover on GitHub.