java – Spring编程bean自动作为代理而不是目标

栏目: Java · 发布时间: 5年前

内容简介:翻译自:https://stackoverflow.com/questions/47360476/spring-programmatic-bean-autowired-as-proxy-instead-of-target

我创建了一个注释,用于创建使用环境中的值填充的ThreadPoolTask​​Executors.但是,当我自动装配bean时,它给了我一个代理并调用代理上的方法给出了错误的值.

如果我手动访问目标类,那么我会得到正确的值.

Executor exec = (Executor) ((Advised) executor).getTargetSource().getTarget();
ThreadPoolTaskExecutor taskExec = (ThreadPoolTaskExecutor) exec;

我一直在摸不着头脑,为什么我得到了一个代理bean,但似乎无法弄明白.

我正在使用注释导入我的注册器类,该类实现ImportBeanDefinitionRegistrar来注册bean.注册商代码如下:

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; 

}

我已经使用以下代码进行了测试:

Spring Boot类:

@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);
    }   
}

spring-boot-starter-parent 1.4.5.RELEASE的所有版本

我写了一个JUnit测试,检查值并通过.它唯一不起作用的是我在Spring Boot eureka应用程序中自动装配它.有什么我可以这样做,它不会自动装配代理bean?我搜索了文档并查看了所有相关的类,但我没有看到任何与它为代理相关的内容.另外,为什么在通过代理访问时会给出错误的值?

似乎您缺少用于注册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);
    }   
}

并且只需记住在自动装配ThreadPoolTask​​Executor实例时使用@Qualifier.参见示例组件

@Component
public class Component {

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

    // you methods
}

翻译自:https://stackoverflow.com/questions/47360476/spring-programmatic-bean-autowired-as-proxy-instead-of-target


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Big Java Late Objects

Big Java Late Objects

Horstmann, Cay S. / 2012-2 / 896.00元

The introductory programming course is difficult. Many students fail to succeed or have trouble in the course because they don't understand the material and do not practice programming sufficiently. ......一起来看看 《Big Java Late Objects》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

MD5 加密
MD5 加密

MD5 加密工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具