Utilizando Spring 3 Autowire en una aplicación Java independiente
-
01-10-2019 - |
Pregunta
Aquí está mi código:
public class Main {
public static void main(String[] args) {
Main p = new Main();
p.start(args);
}
@Autowired
private MyBean myBean;
private void start(String[] args) {
ApplicationContext context =
new ClassPathXmlApplicationContext("META-INF/config.xml");
System.out.println("my beans method: " + myBean.getStr());
}
}
@Service
public class MyBean {
public String getStr() {
return "string";
}
}
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config />
<context:component-scan base-package="mypackage"/>
</beans>
¿Por qué no funciona esto? Consigo NullPointerException
. Es posible el uso de Autowiring en una aplicación independiente?
Solución
El resorte funciona en la aplicación independiente. Está utilizando el camino equivocado para crear un grano de primavera. La forma correcta de hacerlo de esta manera:
@Component
public class Main {
public static void main(String[] args) {
ApplicationContext context =
new ClassPathXmlApplicationContext("META-INF/config.xml");
Main p = context.getBean(Main.class);
p.start(args);
}
@Autowired
private MyBean myBean;
private void start(String[] args) {
System.out.println("my beans method: " + myBean.getStr());
}
}
@Service
public class MyBean {
public String getStr() {
return "string";
}
}
En el primer caso (el de la pregunta), que está creando el objeto por sí mismo, en lugar de obtenerlo a partir del contexto de primavera. Así que la primavera no tienen la oportunidad de Autowire
las dependencias (que hace que el NullPointerException
).
En el segundo caso (el de esta respuesta), se obtiene el grano del contexto primavera y por lo tanto es gestionado y primavera primavera se encarga de autowiring
.
Otros consejos
Primavera se está alejando de archivos XML y los usos anotaciones fuertemente. El siguiente ejemplo es una simple aplicación de la primavera independiente que utiliza la anotación en lugar de archivos XML.
package com.zetcode.bean;
import org.springframework.stereotype.Component;
@Component
public class Message {
private String message = "Hello there!";
public void setMessage(String message){
this.message = message;
}
public String getMessage(){
return message;
}
}
Este es un grano simple. Está decorado con la anotación @Component
para la detección automática por contenedor de primavera.
package com.zetcode.main;
import com.zetcode.bean.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan(basePackages = "com.zetcode")
public class Application {
public static void main(String[] args) {
ApplicationContext context
= new AnnotationConfigApplicationContext(Application.class);
Application p = context.getBean(Application.class);
p.start();
}
@Autowired
private Message message;
private void start() {
System.out.println("Message: " + message.getMessage());
}
}
Esta es la clase principal Application
. Las búsquedas @ComponentScan
de anotación para los componentes. La anotación @Autowired
inyecta el grano en la variable message
. El AnnotationConfigApplicationContext
se utiliza para crear el contexto de aplicación de primavera.
independiente primavera tutorial muestra cómo crear una aplicación de la primavera independiente con XML y anotaciones.
Para Spring 4, utilizando Spring Boot que puede tener el siguiente ejemplo sin utilizar el anti-patrón de conseguir el Bean de la ApplicationContext directamente:
package com.yourproject;
@SpringBootApplication
public class TestBed implements CommandLineRunner {
private MyService myService;
@Autowired
public TestBed(MyService myService){
this.myService = myService;
}
public static void main(String... args) {
SpringApplication.run(TestBed.class, args);
}
@Override
public void run(String... strings) throws Exception {
System.out.println("myService: " + MyService );
}
}
@Service
public class MyService{
public String getSomething() {
return "something";
}
}
Asegúrese de que todos sus servicios inyectados están bajo com.yourproject
o sus sub-paquetes.
Una buena solución sería hacer siguiente,
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class SpringContext implements ApplicationContextAware {
private static ApplicationContext context;
/**
* Returns the Spring managed bean instance of the given class type if it exists.
* Returns null otherwise.
* @param beanClass
* @return
*/
public static <T extends Object> T getBean(Class<T> beanClass) {
return context.getBean(beanClass);
}
@Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
// store ApplicationContext reference to access required beans later on
SpringContext.context = context;
}
}
A continuación, se puede usar como:
YourClass yourClass = SpringContext.getBean(YourClass.class);
Me pareció muy buena solución en la siguiente página web: https: // confluence.jaytaala.com/pages/viewpage.action?pageId=18579463