4

I have an Interface with Component annotation and some classes that implemented it as follows:

@Component
public interface A {
}

public class B implements A {
}
public class C implements A {
}

Also, I have a class with an Autowired variable like this:

public class Collector {
    @Autowired
    private Collection<A> objects;

    public Collection<A> getObjects() {
        return objects;
    }
}

My context file consists of these definitions:

<context:component-scan base-package="org.iust.ce.me"></context:component-scan>

<bean id="objectCollector" class="org.iust.ce.me.Collector" autowire="byType"/>

<bean id="b" class="org.iust.ce.me.B"></bean>
<bean id="c" class="org.iust.ce.me.C"></bean>

And in the main class, I have some codes as follows:

ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
B b = (B) context.getBean("b");
C c = (C) context.getBean("c");
Collector objectCollector = (Collector) context.getBean("objectCollector");

for (A object : objectCollector.getObjects()) {
    System.out.println(object);
}

Output:

org.iust.ce.me.B@1142196
org.iust.ce.me.C@a9255c

These codes work well, but for some reasons I’m not willing to use xml context file. Besides it, I prefer to create the objects with the new operator rather than using the getBean() method. Nevertheless, since the AutoWiring is really good idea in programming, I don’t want to lose it.

Now I have two questions!!

  1. how can I AutoWire classes that implements the A Interface without using the xml context file?
    Is it possible at all?

  2. when I change the scope of a bean from singlton to prototype as follows:

    <bean id="b" class="org.iust.ce.me.B" scope="prototype"></bean>

    and instantiate several beans of it, only the bean which was instantiated during creating context, is injected into AutoWired variable. Why?

Any help will be appreciated.

faghani
  • 569
  • 1
  • 10
  • 25

3 Answers3

9

Not sure the version of Spring you are using. But currently you can use @Configuration to replace .xml. Take a look at @Configuration

Below is the code in documentation

@Configuration
public class ServiceConfig {
    private @Autowired RepositoryConfig repositoryConfig;
    public @Bean TransferService transferService() {
        return new TransferServiceImpl(repositoryConfig.accountRepository());
    }
}

@Configuration
public interface RepositoryConfig {
    @Bean AccountRepository accountRepository();
}

@Configuration
public class DefaultRepositoryConfig implements RepositoryConfig {
    public @Bean AccountRepository accountRepository() {
        return new JdbcAccountRepository(...);
    }
}

@Configuration
@Import({ServiceConfig.class, DefaultRepositoryConfig.class}) // import the concrete config!
public class SystemTestConfig {
    public @Bean DataSource dataSource() { /* return DataSource */ }
}
public static void main(String[] args) {
    ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class);
    TransferService transferService = ctx.getBean(TransferService.class);
    transferService.transfer(100.00, "A123", "C456");
}
manub
  • 3,990
  • 2
  • 24
  • 33
Willy
  • 1,828
  • 16
  • 41
  • Excellent! Wish I could give more than +1 for that. Thanks for finding and posting the code - would never have made it that far down the document... Working fantastically with Neo4j (via [this](http://codepitbull.wordpress.com/2013/05/12/bootstrapping-neo4j-with-spring-data-without-xml)). Again, thank you! – KendallV Jul 10 '13 at 14:36
2

Provided the classes to be managed have been correctly annotated, Spring can scan the application's files to get the information it needs without any xml or java configuration files at all.

AnnotationConfigApplicationContext  context = new AnnotationConfigApplicationContext();
context.scan("com.something.something.etc");
context.refresh();
...context.getBean("name_of_bean");

Note AnnotationConfigApplicationContext is instantiated without any arguments. context.scan("..."); takes a string that tells Spring where to look. i.e. packages

com.something.something.etc.one
com.comething.something.etc.two
will be scanned, and classes within those packages annotated with @Component, @Autowired, etc. will be instatiated and injected where needed.

This approach doesn't seem to be as well documented.

marcus
  • 21
  • 1
0

1- You need to write another class that will do the operation. write @Component to B and C class.

public static void main(){
    ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");  
    InitClass initClass = (InitClass) context.getBean("initClass");  
}


public class InitClass{  
   @Autowired 
   public B b;

   @Autowired 
   public C c;
}

with this you will get B and C without using xml.

2- http://static.springsource.org/spring/docs/3.0.0.M3/reference/html/ch04s04.html Bean scopes are detailed mentioned here. If you want always a new object you should use prototype but creating a new one will be done in different classes. In the same class you should add a new reference.

like

public class InitClass{
    @Autowired 
    public A a1;

    @Autowired 
    public A a2;

}
sgpalit
  • 2,676
  • 2
  • 16
  • 22
  • +0.5! Good answer, but still I have to use XML context file. Moreover, in your code, the classes that implemented `A` Interface manually added to `InitClass`. In my project there is several classes that implemented `A` Interface and I don't want to manually handle them. – faghani Oct 08 '12 at 13:35
  • You have to initialize the xml at startup once to use Spring the first Object that you are going to access from main method should be get with context.getBean the others will be injected if @Autowired exists. For dynamically creating new objects you have to use context.getBean, I think there is no other way in spring. – sgpalit Oct 08 '12 at 14:34
  • I think creating the Spring beans with `new` operator is possible, but I don't know how it can be done. Take a glance at [this question](http://stackoverflow.com/questions/10997092/autowiring-in-spring-bean-component-created-with-new-keyword) – faghani Oct 08 '12 at 17:05
  • At that question there is also an answer, you have to use AOP and compile your projects with maven or ant. I have not done it before maybe you should look to the link provided http://static.springsource.org/spring/docs/current/spring-framework-reference/html/aop.html#aop-atconfigurable and http://www.eclipse.org/aspectj/doc/released/devguide/ltw.html – sgpalit Oct 09 '12 at 06:10