在Spring中为CGLib生成代理的资源注入

时间:2016-02-26 10:25:57

标签: spring dependency-injection mixins cglib

我有一个小问题,我希望有一个人可以复习并帮助我。我正在使用CGLib Mixin代理创建两个接口/实现的混合。这种mixin用于我的春季应用。一切正常:

    static InterfaceBoth createInstance() {
      final Class<?>[] interfaces = new Class[] { InterfaceOne.class, InterfaceTwo.class, InterfaceBoth.class };
      final Object[] delegates = new Object[] { new ClassOne(), new ClassTwo() };
      return ((InterfaceBoth) Mixin.create(interfaces, delegates));
    }

    <!-- Create mixin instance -->
    <bean id="mixin" class="org.literadix.tests.mixins.InterfaceBoth" factory-method="createInstance">
       <property name="password" ref="password"/>
    </bean>

   /**
    * Load mixin by spring bean.
    */
   @Test
   public final void testSpring() {

          final ApplicationContext sCtx = new ClassPathXmlApplicationContext("Application.xml");
          final InterfaceBoth instance = sCtx.getBean(InterfaceBoth.class);

          Assert.assertNotNull(instance.helloOne());
          Assert.assertNotNull(instance.helloTwo());
          Assert.assertNotNull(instance.getPassword());

          log.debug("service instance: {}", instance.getService());
          Assert.assertNotNull(instance.getService());

   }

我还在属性中为该实例注入了一个值(密码)。什么是无效的是通过注释注入资源。我的完整弹簧定义如下:

   <?xml version="1.0" encoding="UTF-8"?>
   <beans xmlns="http://www.springframework.org/schema/beans"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

          xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"

          default-autowire="byName">

       <!-- Enable annotations. -->
       <bean id="annotations" class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/>

       <bean id="password" class="java.lang.String">
           <constructor-arg value="password"/>
       </bean>

       <!-- Service bean -->
       <bean id="service" class="org.literadix.tests.mixins.NewServiceImpl">
       </bean>

       <!-- Create mixin instance -->
       <bean id="mixin" class="org.literadix.tests.mixins.InterfaceBoth" factory-method="createInstance">
           <property name="password" ref="password"/>
       </bean>

   </beans>

   public class ClassOne implements InterfaceOne {

     /**
      * !!! THIS SHOULD BE SET BY SPRING !!!
      */
     @Resource
     public NewService service;    
     ...

一些春季专家能否回顾一下我的例子并告诉我为什么它不能用于解析资源的注释?我想这是一个spring bean加载生命周期的问题。但我无法找到解决方案。

我把所有东西都装进了一个github仓库。如果您想在您的机器上进行测试,请下载它:

https://github.com/literadix/JavaMixins https://github.com/literadix/JavaMixins.git

非常感谢,

马切伊

1 个答案:

答案 0 :(得分:1)

我现在知道如何解决这个问题。 Jeremie B写道,对象的创造超出了春天,这绝对是事实。因此,解决方案是编写一个工厂bean,它由spring框架创建,最初将设置接口。然后可以使用此工厂创建mixin,它将设置所需的依赖项。但是,只需查看以下源代码就难以理解千言万语:

    <bean id="mixinFactory" class="org.literadix.tests.mixins.InterfaceBoth.Factory"/>

    <!-- Create mixin instance -->
    <bean id="mixin" scope="prototype" class="org.literadix.tests.mixins.InterfaceBoth" factory-bean="mixinFactory" factory-method="create">
        <property name="password" ref="password"/>
    </bean>

    public interface InterfaceBoth extends InterfaceOne, InterfaceTwo {

        /** Logger. */
        final static Logger log = LoggerFactory.getLogger(InterfaceBoth.class);

        /**
         * Factory to create a mixin instance from both interfaces and both implementations.
         *
         * @return Merged instance
         */
        static InterfaceBoth createInstance() {
            return new Factory().create();
        }

        static class Factory {

            @Autowired(required = false)
            NewService service;

            InterfaceBoth create(){

                log.debug("created instance {}", service);

                final Class<?>[] interfaces = new Class[] { InterfaceOne.class, InterfaceTwo.class, InterfaceBoth.class };
                final Object[] delegates = new Object[] { new ClassOne() {{setService(service);}}, new ClassTwo() };
                return ((InterfaceBoth) Mixin.create(interfaces, delegates));
            }
        }

    }   

只需查看我的存储库以获取新的和更正的版本:

https://github.com/literadix/JavaMixins

最后一句话:这个解决方案不仅适用于spring,而且由于micin工厂是CGLib工厂,它只能用于普通的java应用程序。