用Spring IOC解决“机器人腿”问题(DI)

时间:2012-12-07 04:35:26

标签: java spring dependency-injection ioc-container guice

使用Guice,可以执行以下操作:

interface Leg {}

_

class LeftLeg implements Leg {
    public String toString() {
        return "LeftLeg";
    }
}

_

class RightLeg implements Leg {
    public String toString() {
        return "RightLeg";
    }
}

_

class Robot {
    final Leg leftLeg_;
    final Leg rightLeg_;

    @Inject
    Robot(@Named("left") Leg leftLeg, @Named("right") Leg rightLeg) {
        leftLeg_ = leftLeg;
        rightLeg_ = rightLeg;
    }

    public String toString() {
        return "leftLeg_=" + leftLeg_ + ", rightLeg_=" + rightLeg_;
    }
}

_

class RobotTest {
    @Test
    public void t1() throws Exception {
        Injector inj = Guice.createInjector(new AnGuiceModule());
        Robot r = inj.getInstance(Robot.class);
        assertEquals(r.toString(), "leftLeg_=LeftLeg, rightLeg_=RightLeg");
    }
}

_

class AnGuiceModule extends AbstractModule {
    protected void configure() {
        bind(Leg.class).annotatedWith(Names.named("left")).to(LeftLeg.class);
        bind(Leg.class).annotatedWith(Names.named("right")).to(RightLeg.class);
    }
}

如何使用JSR-330(可选)注释和JavaConfig在不使用XML配置的情况下使用Spring 3.x(3.1.x或3.2)实现相同的功能?

4 个答案:

答案 0 :(得分:2)

interface Leg {}

_

 @Component
 class LeftLeg implements Leg {
  public String toString() {
    return "LeftLeg";
  }
 }

_

@Component
class RightLeg implements Leg {
  public String toString() {
    return "RightLeg";
 }
}

_

class Robot {
  @Autowired
  Leg leftLeg_;
  @Autowired
  Leg rightLeg_;



  public String toString() {
    return "leftLeg_=" + leftLeg_ + ", rightLeg_=" + rightLeg_;
 }
}

_

@RunWith(SpringJUnit4ClassRunner.class)
class RobotTest {
  @Autowired
  Robot r;
  @Test
  public void t1() throws Exception {
     System.out.println(r);
 }
}

答案 1 :(得分:1)

你可以这样做;虽然这个使用Spring注释,@ Qualifier和@Autowired,虽然我没有看到任何理由不使用@Named和@Inject,但你应该尝试:

public class MovieRecommender {

  private MovieCatalog movieCatalog;
  private CustomerPreferenceDao customerPreferenceDao;

  @Autowired
  public void prepare(@Qualifier("main") MovieCatalog movieCatalog,
                      CustomerPreferenceDao customerPreferenceDao) {
      this.movieCatalog = movieCatalog;
      this.customerPreferenceDao = customerPreferenceDao;
  }

  // ...
}

取自reference

的示例

答案 2 :(得分:1)

我能找到的最接近的是(机器人和腿*类的定义不会改变):

public class RobotTest {

    @Test
    public void t1() throws Exception {
        ApplicationContext ctx = new 
               AnnotationConfigApplicationContext(RobotConfig.class, Robot.class);
        Robot r = ctx.getBean(Robot.class);
        assertEquals("leftLeg_=LeftLeg, rightLeg_=RightLeg", r.toString());
    }
}

@Configuration
class RobotConfig {

    @Bean
    public Leg leftLeg() {
        return new LeftLeg();
    }

    @Bean
    public Leg rightLeg() {
        return new RightLeg();
    }

}

替代方案是:

public class RobotTest {

    @Test public void t1() throws Exception {
        ApplicationContext ctx = new 
               AnnotationConfigApplicationContext(RobotConfig.class);
        Robot r = ctx.getBean(Robot.class);
        assertEquals("leftLeg_=LeftLeg, rightLeg_=RightLeg", r.toString());
    }
}

@Configuration
class RobotConfig {

   @Bean @Scope("prototype") public Robot robot() {
       return new Robot(leftLeg(), rightLeg());
   }

    @Bean @Scope("prototype") public Leg leftLeg() {
        return new LeftLeg();
    }

    @Bean @Scope("prototype") public Leg rightLeg() {
        return new RightLeg();
    }
}

答案 3 :(得分:0)

spring forum描述了一种有趣的方法。 你需要以某种方式获得对子上下文的引用,我不喜欢那里提出的方法,但我应该有其他方法。

用法:

  <bean name="someBean" class="playground.spring.BeanImportFactoryBean">
        <property name="applicationContext" ref="privateCtx"/>
        <property name="importBeanName" value="importBean"/>
    </bean>

FactoryBean代码:

public class BeanImportFactoryBean implements FactoryBean, BeanNameAware {
    transient private final Log log = LogFactory.getLog(this.getClass());

    private String beanName;
    private ApplicationContext applicationContext;
    private String importBeanName;

    public BeanImportFactoryBean() {
    }

    public void setBeanName(String beanName) {
        this.beanName = beanName;
    }

    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    public void setImportBeanName(String importBeanName) {
        this.importBeanName = importBeanName;
    }

    protected String getUsedBeanName() {
        String returnName;
        if (importBeanName == null) {
            returnName = beanName;
        } else {
            returnName = importBeanName;
        }
        return returnName;
    }

    public Object getObject() throws Exception {
        return this.applicationContext.getBean(getUsedBeanName());
    }

    public Class getObjectType() {
        return this.applicationContext.getType(getUsedBeanName());
    }

    public boolean isSingleton() {
        return this.applicationContext.isSingleton(getUsedBeanName());
    }
}