为什么直接创建一个对象可以注册到spring,动态代理的对象不可以注册到spring?

化星星 发布于 2019/04/25 22:00
阅读 484
收藏 0

【华为云1024程序员节·向云而生】预约直播 抽14件华为电子产品礼包!>>>

## 问题:
我分别通过直接new对象,与动态代理生成代理对象加载到spring,并获取bean,
当注册直接new对象正常,而动态代理对象报错:

```
Initialization of bean failed; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'testApiService': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.lang.reflect.InvocationHandler' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
```
## 代码:


```
@Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
        System.out.println("--------------------------------------------");
        String name = "testApiService";
        Object proxyB = (TestApi) () -> {
            System.out.println("------new :↓------");
            return "new Object: hello";
        };
        Class<?> interfaceClass = TestApi.class;
        XHGAProxy xhgaProxy = new XHGAProxy<>(interfaceClass, proxyB);
        // 代理对象------->不能注册到spring
        Object proxyA = Proxy.newProxyInstance(interfaceClass.getClassLoader(),
                new Class[]{interfaceClass}, xhgaProxy);
        TestApi testApiA = (TestApi) proxyA;
        System.out.println("动态代理:" + testApiA.sayHello());
        // new的抽象对象-->可以注册到spring
        TestApi testApiB = (TestApi) proxyB;
        System.out.println("new 对象:" + testApiB.sayHello());
        ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) applicationContext;
        DefaultListableBeanFactory beanFactory =
                (DefaultListableBeanFactory) configurableApplicationContext.getBeanFactory();
        BeanDefinitionBuilder beanDefinitionBuilder =
                BeanDefinitionBuilder.genericBeanDefinition(proxyA.getClass());
        //beanFactory.removeBeanDefinition(name);
        // 注册
        beanFactory.registerBeanDefinition(name, beanDefinitionBuilder.getRawBeanDefinition());
        // 获取加载到spring的bean
        Object bean = applicationContext.getBean(name);
        System.out.println(bean);
    }
```

加载中
0
化星星
化星星

已解决:

//-------↓添加以下代码
beanDefinitionBuilder.addConstructorArgValue(Proxy.getInvocationHandler(proxyA));
AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
beanDefinition.setBeanClass(proxyA.getClass());
//-------↑
0
化星星
化星星

完整代码:

@Component
public class XHGAProxyScan2 implements ApplicationContextAware,InitializingBean {
    ApplicationContext applicationContext;
    @Override
    public void afterPropertiesSet() throws Exception { }
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
        String name = "testApiService";
        Object proxyB = (TestApi) () -> {
            System.out.println("------new :↓------");
            return "new Object: hello";
        };
        Class<?> interfaceClass = TestApi.class;
        XHGAProxy xhgaProxy = new XHGAProxy<>(interfaceClass, proxyB);
        Object proxyA = Proxy.newProxyInstance(interfaceClass.getClassLoader(),
                new Class[]{interfaceClass}, xhgaProxy);
        System.out.println("代理Object:" + proxyA);
        TestApi testApiA = (TestApi) proxyA;
        System.out.println("动态代理:" + testApiA.sayHello());
        // new的抽象对象-->可以注册到spring
        TestApi testApiB = (TestApi) proxyB;
        System.out.println("new 对象:" + testApiB.sayHello());
        ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) applicationContext;
        DefaultListableBeanFactory beanFactory =
                (DefaultListableBeanFactory) configurableApplicationContext.getBeanFactory();
        BeanDefinitionBuilder beanDefinitionBuilder =
                BeanDefinitionBuilder.genericBeanDefinition(proxyA.getClass());
        //-------↓添加以下代码
        beanDefinitionBuilder.addConstructorArgValue(Proxy.getInvocationHandler(proxyA));
        AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
        beanDefinition.setBeanClass(proxyA.getClass());
        //-------↑
        beanFactory.registerBeanDefinition(name, beanDefinitionBuilder.getRawBeanDefinition());
    }
返回顶部
顶部