Autowire取决于子类

时间:2012-02-22 17:47:10

标签: spring inheritance autowired

我有一个抽象类AbstractService,它引用了AbstractDAO

class AbstractService{  
   protected AbstractDAO abstractDAO;  
}

AbstractService将通过ServiceClassAServiceClassB等实际服务类进行扩展, AbstractDAODaoClassADaoClassB等扩展{/ 1}。

根据扩展的AbstractService类,abstractDAO应该是DaoClassADaoClassB等的实例

我可以通过在扩展类中使用abstractDAO setter来实现这一点,如

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

有没有办法让setAbstractDAO类中的setter AbstractService本身 并且abstractDAO获取自动装配,具体取决于子类,可能是SPEL +限定符等

我们不想为此

使用任何XML配置

3 个答案:

答案 0 :(得分:7)

我不会这样做。实际上,ServiceClassA很可能依赖于DaoClassA的某些特定方法。在这种情况下,每次要调用这种特定方法时,都必须将受保护的AbstractDAO强制转换为DaoClassA。

我会使它变得通用,并反转依赖注入的方式:

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
}

答案 1 :(得分:2)

我像你一样解决了类似的问题。我找到了另一种方法,你不必创建setter方法。而不是使用常规构造函数,而是使用Spring自动装配。这是完整的代码:

服务类:

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);
    }

}

注意子类构造函数中的@Qualifier("daoClassA")

字段类:

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");
    }    
}

最后,现在您可以使用具体的Service类和具体的DAO类来调用您的通用服务:(当然您可以在某处自动装配它们)

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

将打印:

I am DaoClassA
I am DaoClassB

答案 2 :(得分:0)

不,没有。您无法访问当前从SPEL填充AutowiredAnnotationBeanPostProcessor的类或bean名称。

您可以覆盖AbstractBeanFactory.evaluateBeanDefinitionString并在beanDefinition中添加BeanExpressionContext作为变量。然后你可以从服务中派生出Dao。在@Value注释中使用SPEL。