Spring Autowiring不适用于抽象类

时间:2012-06-30 09:33:14

标签: spring abstract-class autowired

我有一个项目,我有一个接口,一个实现相同接口的Abstract类,然后是一组实现此接口并扩展Abstract类的具体类。

public interface Invoice
{
   void process();
}

@component
public abstract class AbstractInvoice(){

    @Resource
    protected Writer writer;

    protected validateInvoice(){
        //some implementation
    }
}

@Component
public Class TypeAInvoice() extends AbstractInvoice implements Invoice{

    @Override
    public void process(){
        //... some code
        writer.write();
    }
}

public Interface Writer(){
    public void write();
}

@Component
public class CDWriter implements Writer{
    @Override 
    public void write() { /* implementation.....*/}
}

Spring文件包含组件扫描。

<context:annotation-config>
<context:component-scan base-package="com.xyz" />

我正在使用工厂获取TypeAInvoice发票的实例 现在,在invoice.process()

时,调用write.write()会获得NPE

我不确定我在这里错过了什么。我试图查看组件扫描和范围,但在概念上找不到任何错误。

3 个答案:

答案 0 :(得分:5)

  

我正在使用工厂获取TypeAInvoice发票的实例

根据工厂的不同,这可能是问题所在。如果Factory创建新的TypeAInvoice,则Spring布线不适用。您必须查询Bean的Spring上下文。一种方法(虽然不是很漂亮)是使用ContextLoader

return ContextLoader.getCurrentWebApplicationContext().getBean(TypeAInvoice.class)

我会说静态工厂和春天不能很好地融合在一起。 Spring代表控制反转模式,而工厂代表服务定位模式。我建议你摆脱你的工厂并自动装配你的春豆。

答案 1 :(得分:0)

一切都很好,除了你使用工厂获得TypeAInvoice的事实。如果你像TypeAInvoice typer = new TypeAInvoice()那样创建它,那么spring对它一无所知,Writer没有自动装配,你得到NullPointerException。您应该从spring应用程序上下文中获取bean。

答案 2 :(得分:-1)

在我的情况下,在Spring4应用程序中,我必须使用经典的抽象工厂模式(我从这个想法 - http://java-design-patterns.com/patterns/abstract-factory/)创建实例,每次都有一个操作要完成所以我的代码设计如下:

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

最初为了在抽象类中注入依赖项,我尝试了所有构造型注释,如@ Component,@ Service等,但即使Spring上下文文件具有整个包的ComponentScanning,但在某种程度上创建Subclasses的实例,如CampaignOperation,Super Abstract由于Spring无法识别并注入其依赖项,因此类EO的属性为null。经过多次试验和错误后,我使用了这个**@Configurable(dependencyCheck = true)**注释,最后Spring能够注入依赖项,并且我能够使用这些属性在子类中没有使用太多属性使它们混乱。

<context:annotation-config />
<context:component-scan base-package="com.xyz" />

我也尝试过这些其他参考资料来找到解决方案:

  1. http://www.captaindebug.com/2011/06/implementing-springs-factorybean.html#.WqF5pJPwaAN
  2. http://forum.spring.io/forum/spring-projects/container/46815-problem-with-autowired-in-abstract-class
  3. https://github.com/cavallefano/Abstract-Factory-Pattern-Spring-Annotation
  4. http://www.jcombat.com/spring/factory-implementation-using-servicelocatorfactorybean-in-spring
  5. https://www.madbit.org/blog/programming/1074/1074/#sthash.XEJXdIR5.dpbs
  6. Using abstract factory with Spring framework
  7. Spring and Abstract class - injecting properties in abstract classes
  8. Inject spring dependency in abstract super class
  9. Spring autowire dependency defined in an abstract class
    1. Spring can you autowire inside an abstract class?
  10. 请尝试使用**@Configurable(dependencyCheck = true)**并更新此帖子,如果您遇到任何问题,我可以尝试帮助您。

    所以我的观点恰恰在于你不需要一直从泉水环境中获取豆子。