2012-12-07 2 views
1

Utilisation Guice, on peut effectuer les opérations suivantes:Résolution "jambes de robot" problème avec ressort du CIO (DI)

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

Comment puis-je obtenir la même chose avec 3.x Spring (3.1.x ou 3.2) à l'aide JSR-330 (en option) et annotations JavaConfig sans utiliser Configuration XML?

Répondre

1

Le plus approchante est suivante (La définition du robot et de la jambe * cours ne change pas):

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

} 

alternative serait:

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(); 
    } 
} 
+0

C'est la merde est-il vraiment pas de meilleure solution au printemps? Ce sujet de 2006 présente une approche intéressante de FactoryBean http://forum.spring.io/forum/spring-projects/container/13533-exporting-child-applicationcontext-beans-to-the-parent-applicationcontext –

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); 
} 
} 
+0

Comment faire _constructor injection_? ...J'ai corrigé ma question et déclaré les champs 'final' de sorte qu'il est plus clair que j'ai besoin de Robot immuable Et aussi je veux utiliser des annotations JSR-330 au lieu de Spring spécifique –

+0

L'autre chose que je ne comprends pas dans votre réponse est : comment 'leftLeg_' est lié à' class LeftLeg' et 'rightLeg_' à' class RightLeg' –

1

Vous pouvez le faire comme ceci; bien que celui-ci utilise des annotations de printemps, @Qualifier et @Autowired, bien que je ne vois aucune raison pour cela de ne pas travailler avec @Named et @Inject aussi bien, vous devriez essayer:

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

    // ... 
} 

Exemple tiré de la reference.

0

Il y a une approche intéressante décrite au spring forum. Vous devez obtenir une référence au contexte de l'enfant d'une manière ou d'une autre, je n'aime pas l'approche présentée ici, mais il devrait y avoir d'autres moyens.

Utilisation:

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

Code 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()); 
    } 
}