Autowire subclass dependent

I have an abstract class AbstractService that has a link to AbstractDAO

 class AbstractService{ protected AbstractDAO abstractDAO; } 

AbstractService will extend with valid service classes such as ServiceClassA , ServiceClassB , etc. and AbstractDAO will expand to DaoClassA , DaoClassB , etc.

Depending on which class is distributed by AbstractService , AbstractDAO should be an instance of DaoClassA , DaoClassB , etc.

I can achieve this by setting the abstractDAO setter in an expanding class like

 class ServiceClassA{ @Autowired @Qualifier("daoClassA") public void setAbstractDAO(AbstractDAO abstractDAO) { super.abstractDAO = abstractDAO; } } 

Is there a way to have the setAbstractDAO installer in the AbstractService class and AbstractDAO gets Autowired depending on the subclass, maybe wth SPEL + Qualifier, etc.

We do not want to use any XML configuration for this.

+6
source share
3 answers

I wouldn’t do that. Indeed, there is a good chance that ServiceClassA depends on a specific DaoClassA method. In this case, you will need to drop the protected AbstractDAO to DaoClassA every time you want to call such a specific method.

I would make it general and change the way you enter dependencies:

 public class AbstractService<T extends AbstractDAO> { protected T dao; protected AbstractService(T dao) { this.dao = dao; } // methods common to all the services } public class ServiceClassA extends AbstractService<DaoClassA> { @Autowired public ServiceClassA(DaoClassA dao) { super(dao); } // methods specific to ServiceClassA } 
+7
source

I solved a similar problem like you. I found another way, you do not need to create customization methods. Use regular constructors instead, but use autwiring Spring. Here is the complete code:

Service classes:

 public abstract class AbstractService { protected final AbstractDAO dao; // Constructor forces you to inject dao in subclass public AbstractService(final AbstractDAO dao) { this.dao = dao; } public final void service() { // you can do something generic here with 'dao' // no matter which subclass is injected this.dao.doSomething(); } } @Component public class ServiceClassA extends AbstractService { @Autowired public ServiceClassA(@Qualifier("daoClassA") final AbstractDAO dao) { super(dao); } } @Component public class ServiceClassB extends AbstractService { @Autowired public ServiceClassB(@Qualifier("daoClassB") final AbstractDAO dao) { super(dao); } } 

Pay attention to @Qualifier("daoClassA") in subclass constructors

Field Classes:

 public interface AbstractDAO { public void doSomething(); } @Component public class DaoClassA implements AbstractDAO { @Override public void doSomething() { System.out.println("I am DaoClassA"); } } @Component public class DaoClassB implements AbstractDAO { @Override public void doSomething() { System.out.println("I am DaoClassB"); } } 

And finally, now you can call your shared service a specific service class and a specific DAO class: (of course, you can have them auto-field them somewhere)

 ((AbstractService) context.getBean("serviceClassA")).service(); ((AbstractService) context.getBean("serviceClassB")).service(); 

will print:

 I am DaoClassA I am DaoClassB 
+2
source

No no. You cannot access the class name or bean that is currently AutowiredAnnotationBeanPostProcessor from SPEL.

You can override AbstractBeanFactory.evaluateBeanDefinitionString and add the beanDefinition as variable to BeanExpressionContext . Then you can get Tao from the Service. using SPEL in the @Value annotation.

0
source

Source: https://habr.com/ru/post/909112/


All Articles