Luego de consultar con expertos en el tema, programadores de deferentes áreas y maestros dimos con la respuesta al dilema y la dejamos plasmada en esta publicación.
Solución:
El campo anotado @Autowired
es null
porque Spring no conoce la copia de MileageFeeCalculator
que creaste con new
y no sabía conectarlo automáticamente.
El contenedor Spring Inversion of Control (IoC) tiene tres componentes lógicos principales: un registro (llamado ApplicationContext
) de componentes (beans) que están disponibles para ser utilizados por la aplicación, un sistema configurador que inyecta las dependencias de los objetos en ellos haciendo coincidir las dependencias con beans en el contexto, y un solucionador de dependencias que puede ver una configuración de muchos beans y determinar cómo instanciarlos y configurarlos en el orden necesario.
El contenedor de IoC no es mágico y no tiene forma de conocer los objetos Java a menos que usted le informe de ellos de alguna manera. Cuando usted llama new
, la JVM crea una copia del nuevo objeto y se lo entrega directamente; nunca pasa por el proceso de configuración. Hay tres formas de configurar sus beans.
He publicado todo este código, usando Spring Boot para iniciar, en este proyecto de GitHub; puede ver un proyecto en ejecución completo para cada enfoque para ver todo lo que necesita para que funcione. Etiqueta con el NullPointerException
: nonworking
Inyecta tus frijoles
La opción más preferible es permitir que Spring conecte automáticamente todos sus beans; esto requiere la menor cantidad de código y es el más fácil de mantener. Para que el cableado automático funcione como desea, también conecte automáticamente el MileageFeeCalculator
como esto:
@Controller
public class MileageFeeController
@Autowired
private MileageFeeCalculator calc;
@RequestMapping("/mileage/miles")
@ResponseBody
public float mileageFee(@PathVariable int miles)
return calc.mileageCharge(miles);
Si necesita crear una nueva instancia de su objeto de servicio para diferentes solicitudes, aún puede usar la inyección utilizando los ámbitos de frijol de Spring.
Etiqueta que funciona inyectando el @MileageFeeCalculator
objeto de servicio: working-inject-bean
Utilice @Configurable
Si realmente necesita objetos creados con new
para conectarse automáticamente, puede usar Spring @Configurable
anotación junto con el tejido en tiempo de compilación de AspectJ para inyectar sus objetos. Este enfoque inserta código en el constructor de su objeto que alerta a Spring de que se está creando para que Spring pueda configurar la nueva instancia. Esto requiere un poco de configuración en su compilación (como compilar con ajc
) y activando los controladores de configuración en tiempo de ejecución de Spring (@EnableSpringConfigured
con la sintaxis JavaConfig). Este enfoque es utilizado por el sistema Roo Active Record para permitir new
instancias de sus entidades para obtener la información de persistencia necesaria inyectada.
@Service
@Configurable
public class MileageFeeCalculator
@Autowired
private MileageRateService rateService;
public float mileageCharge(final int miles)
return (miles * rateService.ratePerMile());
Etiqueta que funciona con @Configurable
en el objeto de servicio: working-configurable
Búsqueda manual de frijoles: no recomendado
Este enfoque es adecuado solo para interactuar con código heredado en situaciones especiales. Casi siempre es preferible crear una clase de adaptador singleton que Spring pueda conectar automáticamente y que el código heredado pueda llamar, pero es posible solicitar directamente un bean al contexto de la aplicación Spring.
Para hacer esto, necesita una clase a la que Spring pueda dar una referencia al ApplicationContext
objeto:
@Component
public class ApplicationContextHolder implements ApplicationContextAware
private static ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
context = applicationContext;
public static ApplicationContext getContext()
return context;
Entonces su código heredado puede llamar getContext()
y recupere los frijoles que necesita:
@Controller
public class MileageFeeController
@RequestMapping("/mileage/miles")
@ResponseBody
public float mileageFee(@PathVariable int miles)
MileageFeeCalculator calc = ApplicationContextHolder.getContext().getBean(MileageFeeCalculator.class);
return calc.mileageCharge(miles);
Etiqueta que funciona buscando manualmente el objeto de servicio en el contexto de Spring: working-manual-lookup
Si no está codificando una aplicación web, asegúrese de que su clase en la que se realiza @Autowiring sea un bean de primavera. Por lo general, el contenedor de primavera no conocerá la clase que podríamos considerar como un frijol de primavera. Tenemos que decirle al contenedor Spring sobre nuestras clases de primavera.
Esto se puede lograr configurando en appln-contxt o la mejor manera es anotar la clase como @Componente y no cree la clase anotada con el operador nuevo. Asegúrese de obtenerlo de Appln-context como se muestra a continuación.
@Component
public class MyDemo
@Autowired
private MyService myService;
/**
* @param args
*/
public static void main(String[] args)
// TODO Auto-generated method stub
System.out.println("test");
ApplicationContext ctx=new ClassPathXmlApplicationContext("spring.xml");
System.out.println("ctx>>"+ctx);
Customer c1=null;
MyDemo myDemo=ctx.getBean(MyDemo.class);
System.out.println(myDemo);
myDemo.callService(ctx);
public void callService(ApplicationContext ctx)
// TODO Auto-generated method stub
System.out.println("---callService---");
System.out.println(myService);
myService.callMydao();
En realidad, debe usar Objetos administrados por JVM o Objetos administrados por Spring para invocar métodos. desde su código anterior en su clase de controlador, está creando un nuevo objeto para llamar a su clase de servicio que tiene un objeto cableado automáticamente.
MileageFeeCalculator calc = new MileageFeeCalculator();
por lo que no funcionará de esa manera.
La solución hace que este MileageFeeCalculator sea un objeto cableado automáticamente en el propio Controller.
Cambie su clase de controlador como se muestra a continuación.
@Controller
public class MileageFeeController
@Autowired
MileageFeeCalculator calc;
@RequestMapping("/mileage/miles")
@ResponseBody
public float mileageFee(@PathVariable int miles)
return calc.mileageCharge(miles);
Reseñas y puntuaciones
Si tienes algún reparo y disposición de prosperar nuestro artículo te proponemos realizar una glosa y con deseo lo interpretaremos.