【问题标题】:Autowired annotation doesn't work inside custom dozer converter自动连线注释在自定义推土机转换器中不起作用
【发布时间】:2017-11-25 17:53:48
【问题描述】:

我正在使用下一个推土机自定义转换器

public class MyCustomDozerConverter extends DozerConverter<MyObject, String> {

    @Autowired
    private AppConfig appConfig;

    public MyCustomDozerConverter() {
        super(MyObject.class, String.class);
    }

    @Override
    public String convertTo(MyObject source, String destination) {      
        String myProperty = appConfig.getWhatever();
        // business logic
        return destination;
    }

    @Override
    public MyObject convertFrom(String source, MyObject destination) {
        // business logic
        return null;
    }
}

我的问题是当它通过转换器内部的 convertTo 方法时,我总是得到带有空值的 appConfig 实例,这当然会导致空指针异常

注意:我的spring boot类上面有这些注释:

@SpringBootApplication
@EnableAutoConfiguration
@ComponentScan({"com.xxx"})
@EntityScan("com.xxx")
@EnableJpaRepositories("com.xxx")

【问题讨论】:

  • 是什么创建了MyCustomDozerConverter 的实例?如果 Spring 不这样做,那么依赖注入将不起作用。
  • 是的,创建实例的不是 spring,它似乎 dozer 这样做,这就是为什么 @Autowired 不起作用,但我正在寻求解决这个问题的建议或技巧,明白了吗?跨度>
  • 有比接受的答案更好的选择。请看Custom converter with Spring dependency injection

标签: java spring spring-boot dozer


【解决方案1】:

我通过下一个技巧解决了这个问题:

1- 使用带有 appConfig 属性的静态。

2- 通过 spring 实例化它,所以当推土机使用默认的空构造函数时,它会发现 appConfig 有 已经有一个值(之前由 spring 分配给它)

这是我用于此的代码:

@Component //import org.springframework.stereotype.Component;
public class MyCustomDozerConverter extends DozerConverter<MyObject, String> {

    private static AppConfig appConfig;

    // dozer needs this constructor to create an instance of converter (so it's a mandatory constructor)
    public MyCustomDozerConverter() {
        super(MyObject.class, String.class);
    }

    @Autowired // Spring will pass appConfig to constructor
    public MyCustomDozerConverter(AppConfig appConfig) {
        this();
        this.appConfig = appConfig;
    }

    @Override
    public String convertTo(MyObject source, String destination) {      
        String myProperty = appConfig.getWhatever();
        // business logic
        return destination;
    }

    @Override
    public MyObject convertFrom(String source, MyObject destination) {
        // business logic
        return null;
    }
}

更新:另一种解决方案

另一个技巧是使用 Spring ApplicationContextAware 从 getBean 方法获取单例对象:

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class ApplicationContextHolder implements ApplicationContextAware {
    private static ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        context = applicationContext;
    }

    public static ApplicationContext getContext() {
        return context;
    }
}

然后在 AppConfig 类中创建一个静态方法,并返回一个匹配所需类型的单个 bean 的实例:

import org.springframework.context.annotation.Configuration;
import com.tripbru.ms.experiences.ApplicationContextHolder;

@Configuration
public class AppConfig {

    // Static method used to return an instatnce
    public static AppConfig getInstance() {
        return ApplicationContextHolder.getContext().getBean(AppConfig.class);
    }

    // Properties
}

然后通过 AppConfig.getInstance();

在推土机转换器中直接调用它
public class MyCustomDozerConverter extends DozerConverter<MyObject, String> {

    private static AppConfig appConfig;

    public MyCustomDozerConverter() {
        super(MyObject.class, String.class);
        appConfig = AppConfig.getInstance(); // Here are we intializing it by calling the static method we created.
    }

    @Override
    public String convertTo(MyObject source, String destination) {      
        String myProperty = appConfig.getWhatever();
        // business logic
        return destination;
    }

    @Override
    public MyObject convertFrom(String source, MyObject destination) {
        // business logic
        return null;
    }
}

【讨论】:

    【解决方案2】:

    尝试构造函数依赖注入

    private AppConfig appConfig;
    @Autowired
    MyCustomerDozerConverter(AppConfig appConfig)
    {
        this.appConfig = appConfig;
    }
    

    【讨论】:

    • 不幸的是,这不起作用,这是逻辑因为推土机实例化转换器,所以诀窍不仅是使用它,而且还使用 AppConfig 的静态关键字,请检查我添加的答案。谢谢你的回答:)
    【解决方案3】:

    您可以在 CustomConverter 中添加以下行,以便 Spring 自动装配它。

    public class MyCustomDozerConverter extends DozerConverter<MyObject, String> {
    
    @Autowired
    private AppConfig appConfig;
    
    public MyCustomDozerConverter() {
        super(MyObject.class, String.class);
        SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
    }
    ...
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-21
      相关资源
      最近更新 更多