Is it possible and how to do Assisted Injection in Spring?

前端 未结 3 723
余生分开走
余生分开走 2021-01-04 06:52

In Guice 2 or 3, exists so called Assisted/Partial Inject described here. With this, Guice synthesizes factory implementation (implementing my interface) for my object and s

3条回答
  •  伪装坚强ぢ
    2021-01-04 07:40

    The following does exactly what i asked for. Though, it does not synthesize the implementation of the factory, it is good enough as the factory has access to the injection context so that can use other beans (injectable artifacts) during construction. It uses java based @Configuration instead of XML, but it will work with XML too.

    The factory interface:

    public interface Robot {
    
    }
    
    // Implementation of this is to be injected by the IoC in the Robot instances
    public interface Brain {
        String think();
    }
    
    public class RobotImpl implements Robot {
    
        private final String name_;
        private final Brain brain_;
    
        @Inject
        public RobotImpl(String name, Brain brain) {
            name_ = name;
            brain_ = brain;
        }
    
        public String toString() {
            return "RobotImpl [name_=" + name_ + "] thinks about " + brain_.think();
        }
    }
    
    public class RobotBrain implements Brain {
        public String think() {
            return "an idea";
        }
    }
    


    // The assisted factory type
    public interface RobotFactory {
        Robot newRobot(String name);
    }
    

    // this is the Spring configuration showing how to do the assisted injection

    @Configuration
    class RobotConfig {
    
        @Bean @Scope(SCOPE_PROTOTYPE)
        public RobotFactory robotFactory() {
            return new RobotFactory() {
    
                @Override
                public Robot newRobot(String name) {
                    return new RobotImpl(name, r2dxBrain());
                }
            };
        }
    
        @Bean @Scope(SCOPE_PROTOTYPE)
        public Brain r2dxBrain() {
            return new RobotBrain();
        }
    }
    

    The test code:

    public class RobotTest {
    
        @Test
        public void t1() throws Exception {
            ApplicationContext ctx = new 
                               AnnotationConfigApplicationContext(RobotConfig.class);
            RobotFactory rf = ctx.getBean(RobotFactory.class);
            assertThat(rf.newRobot("R2D2").toString(), 
               equalTo("RobotImpl [name_=R2D2] thins about an idea"));
        }
    
    }
    

    This achieves exactly what Guice does. The tricky difference is the Scope. Spring's default scope is Singleton and Guice's is not (it is prototype).

提交回复
热议问题