对于Spring中的控制反转(IoC)是如何工作的,我有点困惑。

假设我有一个名为UserServiceImpl的服务类,它实现了UserService接口。

@Autowired会怎么做?

在我的控制器中,我如何实例化这个服务的实例?

我能做下面的事情吗?

UserService userService = new UserServiceImpl();

当前回答

@Autowired内部是如何工作的?

例子:

class EnglishGreeting {
   private Greeting greeting;
   //setter and getter
}

class Greeting {
   private String message;
   //setter and getter
}

.xml文件,如果不使用@Autowired将看起来类似:

<bean id="englishGreeting" class="com.bean.EnglishGreeting">
   <property name="greeting" ref="greeting"/>
</bean>

<bean id="greeting" class="com.bean.Greeting">
   <property name="message" value="Hello World"/>
</bean>

如果你使用@Autowired,那么:

class EnglishGreeting {
   @Autowired //so automatically based on the name it will identify the bean and inject.
   private Greeting greeting;
   //setter and getter
}

.xml文件,如果不使用@Autowired将看起来类似:

<bean id="englishGreeting" class="com.bean.EnglishGreeting"></bean>

<bean id="greeting" class="com.bean.Greeting">
   <property name="message" value="Hello World"/>
</bean>

如果仍有疑问,请通过下面的现场演示

@Autowired内部是如何工作的?

其他回答

请记住,您必须通过在spring配置文件中添加元素<context:annotation-config/>来启用@Autowired注释。这将注册AutowiredAnnotationBeanPostProcessor,它负责处理注释。

然后,您可以使用字段注入方法自动装配您的服务。

public class YourController{

 @Autowired
 private UserService userService; 

}

我从Spring @autowired注释中找到了这个

Spring依赖注入帮助您从类中移除耦合。 而不是像这样创建对象:

UserService userService = new UserServiceImpl();

你将在引入DI之后使用它:

@Autowired
private UserService userService;

为了实现这一点,您需要在ServiceConfiguration文件中创建服务的bean。之后,你需要导入ServiceConfiguration类到你的WebApplicationConfiguration类,这样你就可以像这样将bean自动装配到你的控制器中:

public class AccController {

    @Autowired
    private UserService userService;
} 

您可以在这里找到一个基于POC的java配置 的例子。

控制反转的整个概念意味着您无需手动实例化对象并提供所有必要的依赖项。 当你用适当的注释(例如@Service)注释类时,Spring会自动为你实例化对象。如果您不熟悉注释,也可以使用XML文件代替。然而,当您不想加载整个spring上下文时,在单元测试中手动实例化类(使用new关键字)并不是一个坏主意。

首先,也是最重要的一点——所有Spring bean都是受管理的——它们“生活”在一个容器中,称为“应用程序上下文”。

其次,每个应用程序都有一个到该上下文的入口点。Web应用程序有Servlet, JSF使用el-resolver等等。此外,还有一个地方可以引导应用程序上下文并自动连接所有bean。在web应用程序中,这可以是一个启动监听器。

自动装配是通过将一个bean的实例放入另一个bean的实例中的所需字段来实现的。这两个类都应该是bean,也就是说,它们应该被定义为存在于应用程序上下文中。

在应用程序上下文中,什么是“生活”?这意味着实例化对象的是上下文,而不是您。也就是说——你永远不会创建新的UserServiceImpl()——容器会找到每个注入点并在那里设置一个实例。

在你的控制器中,你只有以下内容:

@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") String password) {

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

    }
}

注意事项:

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 of UserService, it will be injected. Apart from the @Autowired annotation, Spring can use XML-configurable autowiring. In that case all fields that have a name or type that matches with an existing bean automatically get a bean injected. In fact, that was the initial idea of autowiring - to have fields injected with dependencies without any configuration. Other annotations like @Inject, @Resource can also be used.

有3种方法可以使用@Autowired创建实例。

1. @Autowired on Properties

注释可以直接用于属性,因此不需要getter和setter:

    @Component("userService")
    public class UserService {

        public String getName() {
            return "service name";
        }
    }

    @Component
    public class UserController {

        @Autowired
        UserService userService

    }

在上面的例子中,当创建UserController时,Spring会查找并注入userService。

2. @自动连接设置

@Autowired注释可用于setter方法。在下面的例子中,当注释被用于setter方法时,当UserController被创建时,setter方法会被userService的实例调用:

public class UserController {

    private UserService userService;

    @Autowired
    public void setUserService(UserService userService) {
            this.userService = userService;
    }
}

3.@Autowired在构造函数上

@Autowired注释也可以用于构造函数。在下面的例子中,当注释用于构造函数时,userService的实例会在创建UserController时作为参数注入到构造函数中:

public class UserController {

    private UserService userService;

    @Autowired
    public UserController(UserService userService) {
        this.userService= userService;
    }
}