【问题标题】:Spring can you autowire inside an abstract class?Spring 你可以在抽象类中自动装配吗?
【发布时间】:2013-11-13 22:32:34
【问题描述】:

Spring 无法自动装配我的对象?是否可以在抽象类中自动装配对象。假设所有模式都在 application-context.xml 中提供

问题:基类和扩展类(如果有)@Service @Component 上应该有什么注释?

示例

abstract class SuperMan {

    @Autowire
    private DatabaseService databaseService;

    abstract void Fly();

    protected void doSuperPowerAction(Thing thing) {

        //busy code

        databaseService.save(thing);

    }
}

扩展类

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/>

【问题讨论】:

标签: spring abstract-class autowired


【解决方案1】:

我有这种弹簧设置工作

具有自动装配字段的抽象类

public abstract class AbstractJobRoute extends RouteBuilder {

    @Autowired
    private GlobalSettingsService settingsService;

以及使用@Component 注释定义的几个子级。

【讨论】:

  • 如果settingsService设置为protected,儿童班可以使用吗?
  • @OrtomalaLokni 是的,他们可以。自动装配不会更改 Java 访问修饰符。
【解决方案2】:

通常,只要您的抽象类位于为组件扫描提供的基础包中,Spring 就应该进行自动装配。

请参阅 thisthis 以获取更多参考。

@Service@Component 都是在 Spring 容器内创建带注释类型的 bean 的原型。正如 Spring Docs 所述,

这个注解作为@Component 的一个特化,允许 通过类路径扫描自动检测实现类。

【讨论】:

    【解决方案3】:

    如果您需要SuperGirl 中的任何数据库操作,您可以将其再次注入SuperGirl

    我认为主要思想是在不同的类中使用相同的对象引用。 那么这个呢:

    //There is no annotation about Spring in the abstract part.
    abstract class SuperMan {
    
    
        private final DatabaseService databaseService;
    
        public SuperMan(DatabaseService databaseService) {
         this.databaseService = databaseService;
        }
    
        abstract void Fly();
    
        protected void doSuperPowerAction(Thing thing) {
    
            //busy code
    
            databaseService.save(thing);
    
        }
    }
    

    @Component
    public class SuperGirl extends SuperMan {
    
    private final DatabaseService databaseService;
    
    @Autowired
    public SuperGirl (DatabaseService databaseService) {
         super(databaseService);
         this.databaseService = databaseService;
        }
    
    @Override
    public void Fly() {
        //busy code
    }
    
    public doSomethingSuperGirlDoes() {
    
        //busy code
    
        doSuperPowerAction(thing)
    
    }
    

    在我看来,一次注入就到处运行 :)

    【讨论】:

      【解决方案4】:

      在我的例子中,在 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、Super Abstract 这样的子类实例时EO 类的属性为 null,因为 spring 无法识别和注入它的依赖项。经过多次试验和错误后,我使用了这个 **@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 Autowiring not working for Abstract classes
      8. Inject spring dependency in abstract super class
      9. Spring and Abstract class - injecting properties in abstract classes
        1. Spring autowire dependency defined in an abstract class

      请尝试使用**@Configurable(dependencyCheck = true)** 并更新此帖子,如果您遇到任何问题,我可能会尝试帮助您。

      【讨论】:

      • 不确定是否使用这样的东西:`ApplicationContextProvider.getApplicationContext().getAutowireCapableBeanFactory().autowireBean(this);` 可以帮助您在不是由您创建的实例上自动装配 bean。
      • 在工厂方法的情况下,我自动连接BeanFactory 并像这样调用beanFactory.getBean(EnrollOperation.class)。这样,如果 EnrollOperation 类有自动装配的注解,它会自动为你注入它们。
      • 仅供参考,在您的枚举开关情况下,您的默认情况将永远不会被调用:) 您还应该检查 type== null ,这不是默认情况
      猜你喜欢
      • 2017-06-12
      • 1970-01-01
      • 1970-01-01
      • 2017-03-14
      • 2013-11-11
      • 2011-01-23
      • 1970-01-01
      • 2014-12-14
      • 1970-01-01
      相关资源
      最近更新 更多