gpt4 book ai didi

java - Spring Boot 自定义 Bean 加载器

转载 作者:行者123 更新时间:2023-12-04 11:30:48 25 4
gpt4 key购买 nike

我正在将 JDBI 与 Spring Boot 结合使用。我关注了这个 guide这导致必须创建一个类:JdbiConfig其中,对于应用程序上下文中想要的每个 dao,您必须添加:

@Bean
public SomeDao someDao(Jdbi jdbi) {
return jdbi.onDemand(SomeDao.class);
}

我想知道 Spring Boot 中是否有某种方法可以创建自定义处理器来创建 bean 并将它们放入应用程序上下文中。关于这如何工作,我有两个想法:
  • 使用自定义注释对 DAO 进行注释 @JdbiDao并写一些东西来捡起来。我曾尝试将这些手动注入(inject)到应用程序启动中,但问题是它们可能无法及时加载以进行注入(inject),因为在类扫描期间无法识别它们。
  • 创建类(class) JdbiDao每个存储库接口(interface)都可以扩展。然后用标准 @Repository 注释接口(interface)并创建一个自定义处理器以通过 Jdbi#onDemand 加载它们

  • 这是我的两个想法,但我不知道有什么方法可以实现。我坚持手动创建一个 bean?以前解决过这个问题吗?

    最佳答案

    策略是扫描您的类路径以查找 dao 接口(interface),然后将它们注册为 bean。
    我们需要:BeanDefinitionRegistryPostProcessor注册额外的 bean 定义和一个 FactoryBean创建 jdbi dao bean 实例。

  • 使用 @JdbiDao 标记您的 dao 接口(interface)
  • @JdbiDao
    public interface SomeDao {
    }
  • 定义一个 FactoryBean创建 jdbi dao
  • public class JdbiDaoBeanFactory implements FactoryBean<Object>, InitializingBean {

    private final Jdbi jdbi;
    private final Class<?> jdbiDaoClass;
    private volatile Object jdbiDaoBean;

    public JdbiDaoBeanFactory(Jdbi jdbi, Class<?> jdbiDaoClass) {
    this.jdbi = jdbi;
    this.jdbiDaoClass = jdbiDaoClass;
    }

    @Override
    public Object getObject() throws Exception {
    return jdbiDaoBean;
    }

    @Override
    public Class<?> getObjectType() {
    return jdbiDaoClass;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
    jdbiDaoBean = jdbi.onDemand(jdbiDaoClass);
    }
    }
  • 扫描 @JdbiDao 的类路径带注释的接口(interface):
  • public class JdbiBeanFactoryPostProcessor
    implements BeanDefinitionRegistryPostProcessor, ResourceLoaderAware, EnvironmentAware, BeanClassLoaderAware, BeanFactoryAware {

    private BeanFactory beanFactory;
    private ResourceLoader resourceLoader;
    private Environment environment;
    private ClassLoader classLoader;

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
    this.resourceLoader = resourceLoader;
    }

    @Override
    public void setEnvironment(Environment environment) {
    this.environment = environment;
    }

    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
    this.classLoader = classLoader;
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
    this.beanFactory = beanFactory;
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {

    }

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
    ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false) {
    @Override
    protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
    // By default, scanner does not accept regular interface without @Lookup method, bypass this
    return true;
    }
    };
    scanner.setEnvironment(environment);
    scanner.setResourceLoader(resourceLoader);
    scanner.addIncludeFilter(new AnnotationTypeFilter(JdbiDao.class));
    List<String> basePackages = AutoConfigurationPackages.get(beanFactory);
    basePackages.stream()
    .map(scanner::findCandidateComponents)
    .flatMap(Collection::stream)
    .forEach(bd -> registerJdbiDaoBeanFactory(registry, bd));
    }

    private void registerJdbiDaoBeanFactory(BeanDefinitionRegistry registry, BeanDefinition bd) {
    GenericBeanDefinition beanDefinition = (GenericBeanDefinition) bd;
    Class<?> jdbiDaoClass;
    try {
    jdbiDaoClass = beanDefinition.resolveBeanClass(classLoader);
    } catch (ClassNotFoundException e) {
    throw new RuntimeException(e);
    }
    beanDefinition.setBeanClass(JdbiDaoBeanFactory.class);
    // Add dependency to your `Jdbi` bean by name
    beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(new RuntimeBeanReference("jdbi"));
    beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(Objects.requireNonNull(jdbiDaoClass));

    registry.registerBeanDefinition(jdbiDaoClass.getName(), beanDefinition);
    }
    }
  • 导入我们的 JdbiBeanFactoryPostProcessor
  • @SpringBootApplication
    @Import(JdbiBeanFactoryPostProcessor.class)
    public class Application {
    }

    关于java - Spring Boot 自定义 Bean 加载器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61526870/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com