Conceptos clave: @Bean
y @Configuration
Los artefactos centrales en el nuevo soporte de configuración de Java de Spring son clases, marcadas con el @Configuration
y los métodos marcados con la anotación @Bean
.
La anotación @Bean
se utiliza para indicar que El método crea una instancia, configura e inicializa un nuevo objeto que será
administrado por el contenedor Spring IoC. Para aquellos familiarizados con la configuración XML <beans/>
de Spring, la anotación @Bean
juega el mismo papel que el elemento <bean/>
.
Puede utilizar métodos anotados @Bean
con cualquier anotación @Component
de Spring.
Sin embargo, se usan con mayor frecuencia con beans anotados con @Configuration
.
Anotar una
clase con @Configuration
indica que su propósito principal es ser un Definiciones de beans de origen.
Además, las clases anotadas con @Configuration
le permiten definir dependencias entre beans llamando a
otros métodos @Bean
en la misma clase. La clase más simple posible, anotada con
@Configuration
, se ve así:
@Configuration
public class AppConfig {
@Bean
public MyService myService() {
return new MyServiceImpl();
}
}
@Configuration
class AppConfig {
@Bean
fun myService(): MyService {
return MyServiceImpl()
}
}
La clase anterior AppConfig
es equivalente a la siguiente clase XML <beans/> from
Spring:
<beans>
<bean id="myService" class="com.acme.services.MyServiceImpl"/>
</beans>
Las anotaciones @Bean
y @Configuration
se analizan en detalle en las siguientes
secciones. Sin embargo, primero veremos las diferentes formas de crear un contenedor Spring usando una configuración
basada en Java.
Creación de una instancia de un contenedor Spring usando AnnotationConfigApplicationContext
Lo siguiente Las secciones describen AnnotationConfigApplicationContext
introducido en Spring 3.0.
Esta implementación genérica de la interfaz ApplicationContext
puede aceptar como entrada no solo
clases anotadas con la anotación @Configuration
, sino también clases regulares anotadas con la
anotación @Component
anotación, así como clases anotadas con metadatos de JSR-330.
Si las
clases anotadas con la anotación @Configuration
se especifican como entrada, la clase misma anotada con
@Configuration
se registra como una definición de bean y todos los métodos declarados en la clase que
están marcados con la anotación @Bean
también se registran como definiciones de bean.
Si se
especifican clases marcadas con la anotación @Component
, o de JSR-330, se registran como definiciones
de beans y metadatos de inyección de dependencia como @Autowired
o Se supone que
@Inject
se usa en estas clases cuando sea necesario.
Diseño simple
Así como los
archivos Spring XML se usan como entrada al crear un ClassPathXmlApplicationContext
, puede usar
clases, anotadas con @Configuration
, como entrada al crear
AnnotationConfigApplicationContext
. Esto le permite utilizar todo el contenedor Spring sin XML, como se
muestra en el siguiente ejemplo:
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
MyService myService = ctx.getBean(MyService.class);
myService.doStuff();
}
import org.springframework.beans.factory.getBean
fun main() {
val ctx = AnnotationConfigApplicationContext(AppConfig::class.java)
val myService = ctx.getBean<MyService>()
myService.doStuff()
}
Como se mencionó anteriormente, AnnotationConfigApplicationContext
no se limita a trabajar solo
con clases anotadas con @Configuration
. Cualquier clase anotada @Component
o JSR-330 se
puede proporcionar como entrada al constructor, como se muestra en el siguiente ejemplo:
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(MyServiceImpl.class, Dependency1.class, Dependency2.class);
MyService myService = ctx.getBean(MyService.class);
myService.doStuff();
}
import org.springframework.beans.factory.getBean
fun main() {
val ctx = AnnotationConfigApplicationContext(MyServiceImpl::class.java, Dependency1::class.java, Dependency2::class.java)
val myService = ctx.getBean<MyService>()
myService.doStuff()
}
El ejemplo anterior supone que MyServiceImpl
, Dependency1
y Dependency2
usan anotaciones de inyección de dependencia de Spring como @Autowired
.
Construyendo un
contenedor mediante programación usando register(Class<?>…)
Puedes crear
AnnotationConfigApplicationContext
usando un constructor sin argumentos y luego configurándolo usando el
método register()
. Este enfoque es especialmente útil al construir AnnotationConfigApplicationContext
mediante programación. El siguiente ejemplo muestra cómo hacer esto:
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(AppConfig.class, OtherConfig.class);
ctx.register(AdditionalConfig.class);
ctx.refresh();
MyService myService = ctx.getBean(MyService.class);
myService.doStuff();
}
import org.springframework.beans.factory.getBean
fun main() {
val ctx = AnnotationConfigApplicationContext()
ctx.register(AppConfig::class.java, OtherConfig::class.java)
ctx.register(AdditionalConfig::class.java)
ctx.refresh()
val myService = ctx.getBean<MyService>()
myService.doStuff()
}
Habilite el escaneo de componentes usando scan(String...)
Para habilitar escaneando
componentes, puede anotar su clase con @Configuration
de esta manera:
@Configuration
@ComponentScan(basePackages = "com.acme")
public class AppConfig {
// ...
}
- Esta anotación le permite escanear componentes.
@Configuration
@ComponentScan(basePackages = ["com.acme"])
class AppConfig {
// ...
}
- Esta anotación permite escanear componentes.
Los usuarios experimentados de Spring pueden estar familiarizados con el
equivalente Spring de la declaración XML del espacio de nombres context:
, que se muestra en el
siguiente ejemplo:
<beans>
<context:component-scan base-package="com.acme"/>
</beans>
En el ejemplo anterior, el paquete com.acme
se analiza en busca de clases. anotadas con @Component
,
y estas clases se registran como definiciones de Spring Bean en el contenedor. AnnotationConfigApplicationContext
expone el método scan(String...)
para proporcionar la misma funcionalidad de escaneo de componentes
como se muestra en el siguiente ejemplo:
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.scan("com.acme");
ctx.refresh();
MyService myService = ctx.getBean(MyService.class);
}
fun main() {
val ctx = AnnotationConfigApplicationContext()
ctx.scan("com.acme")
ctx.refresh()
val myService = ctx.getBean<MyService>()
}
@Configuration
están
metaanotadas con @Component
y, por lo tanto, son candidatas para el escaneo de componentes. En el
ejemplo anterior, asumiendo que AppConfig
está declarado en el paquete com.acme
(o
cualquier otro paquete debajo de él), se intercepta durante la llamada a scan()
. Después de refresh()
,
todos sus métodos anotados con @Bean
se procesan y registran como definiciones de beans en el
contenedor.
Soporte de aplicaciones web con AnnotationConfigWebApplicationContext
Se puede acceder a la variante WebApplicationContext
de la clase AnnotationConfigApplicationContext
mediante AnnotationConfigWebApplicationContext
. Puede utilizar esta implementación al configurar un
escucha de servlet ContextLoaderListener
de Spring, DispatcherServlet
de Spring MVC, etc.
El siguiente fragmento web.xml
configura una aplicación web típica en Spring MVC (tenga en cuenta el
uso de los parámetros de contexto y de inicio contextClass
):
<web-app>
<!-- Configuring ContextLoaderListener to use AnnotationConfigWebApplicationContext
instead of the standard XmlWebApplicationContext -->
<context-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</context-param>
<!-- The configuration location must consist of one or more comma- or space-separated
fully qualified class names annotated with @Configuration. Full package names can also be -->
<context-param>
<param-name>contextConfigLocation>/param-name>
<param-value>com.acme.AppConfig</param-value>
</context-param>
<!-- We bootstrap the root application context as usual, using ContextLoaderListener -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-classм
</listener>
<!-- Declare the DispatcherServlet in Spring MVC as usual -->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- Configure the DispatcherServlet to use AnnotationConfigWebApplicationContext
instead of the standard XmlWebApplicationContext -->
<init-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</init-param>
<!-- Again, configuration locations must consist of one or more comma- or space-separated
and fully qualified class names annotated with @Configuration -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.acme.web.MvcConfig</param-value>
</init-param>
</servlet>
<!-- map all requests for /app/* to the dispatcher servlet -->
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
</web-app>
GenericWebApplicationContext
se
puede utilizar como alternativa a AnnotationConfigWebApplicationContext
. Para obtener más información,
consulte el javadoc en GenericWebApplicationContext
.