当前位置: 首页 > 知识库问答 >
问题:

Spring编程bean自动连接为代理而不是目标

仲孙子辰
2023-03-14
Executor exec = (Executor) ((Advised) executor).getTargetSource().getTarget();
ThreadPoolTaskExecutor taskExec = (ThreadPoolTaskExecutor) exec;
public class ExecutorEnumerationRegistrar implements ImportBeanDefinitionRegistrar, EnvironmentAware {

    public static final String CORE_POOL_SIZE = "corePoolSize";
    public static final String MAX_POOL_SIZE = "maxPoolSize";
    public static final String QUEUE_CAPACITY = "queueCapacity";
    public static final String THREAD_NAME_PREFIX = "threadNamePrefix";
    private static final String REJECTED_EXECUTION_HANDLER = "rejectedExecutionHandler";
    private static final String NAMES = "names";
    private static final String REJECTED_HANDLER = "rejectedHandler";
    private Environment env;

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        Map<String, Object> attrs = importingClassMetadata.getAnnotationAttributes(ThreadPoolTaskExecutorCreator.class.getName(), true);
        final String[] beanNames = (String[]) attrs.get(NAMES);
        final String[] policyClass = (String[]) attrs.get(REJECTED_HANDLER);
        for (int x = 0; x < beanNames.length; x++) {
            createAndRegisterBean(beanNames[x], policyClass[x], registry);
        }
    }

    private void createAndRegisterBean(String name, String policyClass, BeanDefinitionRegistry registry) {
        GenericBeanDefinition bd = new GenericBeanDefinition();
        bd.setBeanClass(ThreadPoolTaskExecutor.class);
        bd.setAutowireCandidate(true);
        bd.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
        MutablePropertyValues mpv = bd.getPropertyValues();
        populateProperties(mpv, name, policyClass);
        registry.registerBeanDefinition(name, bd);
    }

    private void populateProperties(MutablePropertyValues mpv, String name, String policyClass) {
        mpv.add(CORE_POOL_SIZE, Integer.valueOf(env.getProperty(name + "." + CORE_POOL_SIZE)));
        mpv.add(MAX_POOL_SIZE, Integer.valueOf(env.getProperty(name + "." + MAX_POOL_SIZE)));
        mpv.add(QUEUE_CAPACITY, Integer.valueOf(env.getProperty(name + "." + QUEUE_CAPACITY)));
        try {
            mpv.add(REJECTED_EXECUTION_HANDLER, Class.forName(policyClass).newInstance());
        } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
            e.printStackTrace();
        }
        mpv.add(THREAD_NAME_PREFIX, name + "-");
    }

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

}
@Retention(RetentionPolicy.RUNTIME)  
@Target(ElementType.TYPE) 
@Documented 
@Import(ExecutorEnumerationRegistrar.class) 
public @interface ThreadPoolTaskExecutorCreator{ 

    String[] names(); 

    String[] rejectedHandler() default ThreadPoolPolicyHandlers.CALLER_RUNS_POLICY; 

} 
@EnableDiscoveryClient
@ComponentScan("my.test.classes")
@ThreadPoolTaskExecutorCreator(names = {"testExecutor"}, rejectedHandler = ThreadPoolPolicyHandlers.DISCARD_POLICY) 
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, 
    SessionAutoConfiguration.class,
    DataSourceTransactionManagerAutoConfiguration.class, 
    JpaRepositoriesAutoConfiguration.class,
    JndiDataSourceAutoConfiguration.class, 
    JndiConnectionFactoryAutoConfiguration.class,
    RedisAutoConfiguration.class, RedisRepositoriesAutoConfiguration.class})
public class TestBoot {

    public static void main(String[] args) {
        SpringApplication.run(TestBoot.class, args);
    }   
}

共有1个答案

韦衡
2023-03-14

看来您缺少了注册ImportBeanDefinitionRegistrar实例的代码(在您的示例中是ExecutorEnumerationRegistrar),因此有两种方法可以注册ImportBeanDefinitionRegistrar直接使用@Import注释,或者实现ImportSelector接口,它可以提供更多的通用配置选项。

对于您的情况,只需在configuration类上添加@import({executorEnumerationRegistrar.class})就可以完成此任务。

@EnableDiscoveryClient
@ComponentScan("my.test.classes")
@ThreadPoolTaskExecutorCreator(names = {"testExecutor"}, rejectedHandler = ThreadPoolPolicyHandlers.DISCARD_POLICY)
// THIS IS REQUIRED
@Import({ExecutorEnumerationRegistrar.class})
// See Above
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, 
SessionAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class, 
JpaRepositoriesAutoConfiguration.class,
JndiDataSourceAutoConfiguration.class, 
JndiConnectionFactoryAutoConfiguration.class,
RedisAutoConfiguration.class, RedisRepositoriesAutoConfiguration.class})
public class TestBoot {

    public static void main(String[] args) {
        SpringApplication.run(TestBoot.class, args);
    }   
}

并且只需记住在自动生成ThreadPoolTaskExecutor的实例时使用@qualifier。参见示例组件

@Component
public class Component {

    @Autowired
    @Qualifier("testExecutor")
    private ThreadPoolTaskExecutor exec;

    // you methods
}
 类似资料:
  • 我在spring中定义了一个映射: 然后我将这个bean自动转换为一个属性,该属性定义为: 干杯。

  • 我是Spring的新手。我正面临Spring-Boot的问题。我正在尝试将外部配置文件中的字段自动装配到自动装配的bean中。我有以下类 应用程序。Java语言 AppConfig。Java语言 服务接口 服务1 我无法在App类的postconstruct方法中显示服务名称变量。我这样做对吗?

  • 我定义了一个简单的类来保存我的elasticsearch客户端(称为ElasticClientConfig.java)的配置属性。 我为我的开发、生产和测试环境定义了一个配置。每个配置概要文件都有一个方法,该方法返回ElasticClientConfig类型的bean,并使用特定于环境的参数构建一个MyConfig对象。以下是开发版本: 我在我的网站中将我的活动配置文件设置为“dev”。xml文件

  • 我正在开发一个连接到MySQL数据库的非常小的应用程序。 我正在尝试创建表记录,但得到“无事务处理”。 我已经准备好了所有合适的东西: 服务接口MyService及其实现MyServiceImpl 我已使用@service注释了服务impl 在控制器中,我为字段@Autowired MyService使用了接口名称 我有正确的事务配置,因为它最初是由Roo生成的 存在一个公共方法MyService

  • 我读过这段文档: RabbitMQ自动连接/拓扑恢复 自Spring AMQP的第一个版本以来,该框架在代理失败的情况下提供了自己的连接和通道恢复。此外,如第3.1.10节“配置代理”所述,RabbitAdmin将在重新建立连接时重新声明任何基础结构bean(队列等)。因此,它不依赖amqp客户端库现在提供的自动恢复。Spring AMQP现在使用4.0。amqp客户端的x版本,默认情况下已启用自

  • 我创建了自己的库(com.custom.mylib),它返回一个字符串,如下所示。 我创建了一个将使用上述库的项目。我已将lib作为pom依赖项包含在内。但是当我尝试从我的应用程序调用库方法时。我得到了下面的错误。如何解决它? 请考虑在您的配置中定义一个“com.custom.mylog.MyLibrary”类型的bean。 我在application.properties文件中也有下面的内容,这