繁体   English   中英

Autowire Java 使用来自外部库的 NewInstance 创建的 Bean

[英]Autowire Java Bean created with NewInstance from an external library

我正在做一个 Spring 引导项目并使用 OpenCSV 库将一些 csv 解析为 POJO 以持久保存到数据库。

OpenCSV 使用注释@CsvCustomBindByName到 map 一个 CSV 字段到一个 Java ZA8CFDE6331BD54B62ZF88119ZF81119。

converter = DepartmentConverter.class是一个自定义转换器,实例化为:

Class<? extends AbstractBeanField<T,K>>.newInstance() 

由库,在运行时。

问题是因为自定义字段转换器是由 OpenCSV 库反射实例化的,它不能自动装配 bean,因为它没有在 Spring 上下文中注册。

我怎样才能让动态实例化的转换器知道 Spring 上下文或其他方式。 某种拦截器? 谢谢!

//Spring Managed class
public class Specialization { 
   
    @CsvCustomBindByName(required = true, converter = DepartmentConverter.class)
    private Department department;
    
    ....
}

在我的 DepartmentConverter 中,我需要使用 Spring JPARepository 来检索一些数据。 DepartmentRepository 无法自动装配。

    @Component
public class DepartmentConverter extends AbstractBeanField<Department, String> {

    @Autowired
    private DepartmentRepository departmentRepository;

    public DepartmentConverter() {

    }

    @Override protected Object convert(String val) throws CsvConstraintViolationException, ResourceNotFoundException {
        //use departmentRepository
        ...
    }
}

您所指的newInstance()调用位于HeaderColumnNameMappingStrategy class 中,它调用instantiateCustomConverter()方法来执行newInstance()调用。

创建一个子类并覆盖该方法:

@Override
protected BeanField<T, K> instantiateCustomConverter(Class<? extends AbstractBeanField<T, K>> converter) throws CsvBadConverterException {
    BeanField<T, K> c = super.instantiateCustomConverter(converter);
    // TODO autowire here
    return c;
}

Spring @Autowired on a class new instance 的答案中可以看出,您可以按如下方式进行自动装配:

autowireCapableBeanFactory.autowireBean(c);

所以子类会是这样的:

public class AutowiredConverterMappingStrategy extends HeaderColumnNameMappingStrategy {

    private final AutowireCapableBeanFactory beanFactory;

    public AutowiredConverterMappingStrategy(AutowireCapableBeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }

    @Override
    protected BeanField<T, K> instantiateCustomConverter(Class<? extends AbstractBeanField<T, K>> converter) throws CsvBadConverterException {
        BeanField<T, K> c = super.instantiateCustomConverter(converter);
        this.beanFactory.autowireBean(c);
        return c;
    }
}

要使用它,你需要这样的东西:

@Component
class MyComponent {

    @Autowired
    private AutowireCapableBeanFactory beanFactory;

    public <T> List<T> parseCsvToBean(Reader reader, Class<? extends T> type) {
        return new CsvToBeanBuilder(reader)
                .withType(type)
                .withMappingStrategy(new AutowiredConverterMappingStrategy(this.beanFactory))
                .build()
                .parse();
    }
}

这当然只是一个例子。 您的CsvToBean设置可能更复杂,但关键部分是withMappingStrategy()调用,并且代码本身位于 Spring Bean 中,因此它可以访问 bean 工厂。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM