4

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

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()获取 NPEwrite.write()

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

4

3 回答 3

5

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

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

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

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

于 2012-06-30T09:47:08.703 回答
0

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

于 2012-06-30T09:48:28.467 回答
-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,但不知何故,在创建像 CampaignOperation 这样的子类实例时,超级抽象类 EO 是由于spring无法识别和注入其依赖项,因此其属性为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?

Please try using **@Configurable(dependencyCheck = true)** and update this post, I might try helping you if you face any problems.

So precisely my point here is you don't need to get a bean from spring context all the time.

于 2018-03-09T23:11:41.817 回答