views:

96

answers:

2

I'm a little confused as to how the IOC works in spring.

Say I have a service class called UserServiceImpl that implements UserService interface.

How would this be auto-wired?

And in my Controllers action, how would I instantiate an instance of this service?

Would I just do:

UserService userService = new UserServiceImpl();
+7  A: 

First, and most important - all spring beans are managed - they "live" inside a container, called "application context".

Second, each application has an entry point to that context. Web applications use a Servlet, JSF uses a el-resolver, standalones use the main method, etc. The entry point bootstraps the application context and autowires all beans.

Autowiring happens by placing an instance of one bean into the desired location in an instance of another bean. Both classes should be beans, i.e. they should be defined to live in the application context.

What is "living" in the application context? This means that the context instantiates the objects, not you. I.e. - you never make new UserServiceImpl() - the container finds each injection point and sets an instance there.

In your controllers, you just have the folloing:

@Controller // defines that this class is a spring bean
@RequestMapping("/users")
public class SomeController {

    // tells the application context to inject an instance of UserService here
    @Autowired
    private UserService userService;

    @RequestMapping("/login")
    public void login(@RequestParam("username") String username,
           @RequestParam("password") password) {

        // the UserServiceImpl is already injected and you can use it
        userService.login(username, password);

    }
}

A few notes:

  • in your applicationContext.xml you should enable the <context:component-scan> so that classes are scanned for the @Controller, @Service, etc. annotations
  • the entry point for a spring-mvc application is the DispatcherServlet, but it is hidden from you, and hence the direct interaction and bootstrapping of the application context happens behind the scene.
  • UserServiceImpl should also be defined as bean - either using <bean id=".." class=".."> or using the @Service annotation. Since it will be the only implementor or UserService, it will be injected.
Bozho
your last point, so in the implmentation of the interface, UserServiceImpl, I annotate with @Service correct? Great answer, REALLY cleared things up for me.
Blankman
is UserService userService the interface?
Blankman
yes, UserServiceImpl is annotated with Service, and UserService is the interface
Bozho
+3  A: 

Depends on whether you went the annotations route or the bean XML definition route.

Say you had the beans defined in your applicationContext.xml:

<beans ...>

    <bean id="userService" class="com.foo.UserServiceImpl"/>

    <bean id="fooController" class="com.foo.FooController"/>

</beans>

The autowiring happens when the application starts up. So, in fooController, which for arguments sake wants to use the UserServiceImpl class, you'd annotate it as follows:

public class FooController {

    // You could also annotate the setUserService method instead of this
    @Autowired
    private UserService userService;

    // rest of class goes here
}

When it sees @Autowired, Spring will look for a class that matches the property in the applicationContext, and inject it automatically. If you have more than 1 UserService bean, then you'll have to qualify which one it should use.

If you do the following:

UserService service = new UserServiceImpl();

It will not pick up the @Autowired unless you set it yourself.

Ben J