lib - Spring ¿puedes autocablear dentro de una clase abstracta?
tag lib jstl (3)
Spring está fallando en conectar mi objeto automáticamente? ¿Es posible autoaumentar un objeto dentro de una clase abstracta? Suponga que todos los esquemas se suministran en application-context.xml
Pregunta: ¿Qué anotación debe estar en la base y extender las clases (si corresponde) @Service @Component?
Ejemplo
abstract class SuperMan {
@Autowire
private DatabaseService databaseService;
abstract void Fly();
protected void doSuperPowerAction(Thing thing) {
//busy code
databaseService.save(thing);
}
}
Clase extendida
public class SuperGirl extends SuperMan {
@Override
public void Fly() {
//busy code
}
public doSomethingSuperGirlDoes() {
//busy code
doSuperPowerAction(thing)
}
application-context.xml
<context:component-scan base-package="com.baseLocation" />
<context:annotation-config/>
En mi caso, dentro de una aplicación Spring4, tuve que usar un patrón abstracto de fábrica clásico (para el cual tomé la idea de - http://java-design-patterns.com/patterns/abstract-factory/ ) para crear instancias cada uno y cada vez que había una operación por hacer. Así que mi código debía diseñarse como:
public abstract class EO {
@Autowired
protected SmsNotificationService smsNotificationService;
@Autowired
protected SendEmailService sendEmailService;
...
protected abstract void executeOperation(GenericMessage gMessage);
}
public final class OperationsExecutor {
public enum OperationsType {
ENROLL, CAMPAIGN
}
private OperationsExecutor() {
}
public static Object delegateOperation(OperationsType type, Object obj)
{
switch(type) {
case ENROLL:
if (obj == null) {
return new EnrollOperation();
}
return EnrollOperation.validateRequestParams(obj);
case CAMPAIGN:
if (obj == null) {
return new CampaignOperation();
}
return CampaignOperation.validateRequestParams(obj);
default:
throw new IllegalArgumentException("OperationsType not supported.");
}
}
}
@Configurable(dependencyCheck = true)
public class CampaignOperation extends EO {
@Override
public void executeOperation(GenericMessage genericMessage) {
LOGGER.info("This is CAMPAIGN Operation: " + genericMessage);
}
}
Inicialmente para inyectar las dependencias en la clase abstracta probé todas las anotaciones de estereotipos como @Component, @Service, etc. aunque el archivo de contexto Spring tenía ComponentScanning para todo el paquete, pero de alguna manera, mientras creaba instancias de Subclases como CampaignOperation, la clase Super Abstract EO era teniendo nulo sus propiedades ya que Spring no pudo reconocer e inyectar sus dependencias. Después de mucha prueba y error usé esta anotación **@Configurable(dependencyCheck = true)**
y finalmente Spring pudo inyectar las dependencias y pude use las propiedades en la subclase sin saturarlas con demasiadas propiedades.
<context:annotation-config />
<context:component-scan base-package="com.xyz" />
También probé estas otras referencias para encontrar una solución:
- http://www.captaindebug.com/2011/06/implementing-springs-factorybean.html#.WqF5pJPwaAN
- http://forum.spring.io/forum/spring-projects/container/46815-problem-with-autowired-in-abstract-class
- https://github.com/cavallefano/Abstract-Factory-Pattern-Spring-Annotation
- http://www.jcombat.com/spring/factory-implementation-using-servicelocatorfactorybean-in-spring
- https://www.madbit.org/blog/programming/1074/1074/#sthash.XEJXdIR5.dpbs
- Uso de fábrica abstracta con marco Spring
- Spring Autowiring no funciona para clases abstractas
- Inyectar la dependencia de primavera en super clase abstracta
- Primavera y clase abstracta - propiedades de inyección en clases abstractas
Intenta usar **@Configurable(dependencyCheck = true)**
y actualiza esta publicación, podría intentar ayudarte si tienes algún problema.
Normalmente, Spring debe realizar el autoenlace, siempre y cuando su clase abstracta esté en el paquete base proporcionado para el escaneo de componentes.
Ver this y this para referencia futura.
@Service
y @Component
son ambos estereotipos que crean beans del tipo anotado dentro del contenedor Spring. Como Spring Docs declara,
Esta anotación sirve como una especialización de @Component, lo que permite que las clases de implementación sean detectadas automáticamente a través del escaneo de classpath.
Tengo ese tipo de configuración de primavera trabajando
una clase abstracta con un campo autocableado
public abstract class AbstractJobRoute extends RouteBuilder {
@Autowired
private GlobalSettingsService settingsService;
y varios niños definidos con la anotación @Component
.