自动装配如何在Spring工作?

Bla*_*man 481 java spring spring-mvc ioc-container autowired

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

假设我有一个名为的UserServiceImpl实现UserService接口的服务类.

怎么会这样@Autowired

而在我Controllers,我怎么会instantiateinstance这个服务的?

我会做以下吗?

UserService userService = new UserServiceImpl();
Run Code Online (Sandbox Code Playgroud)

Boz*_*zho 676

首先,也是最重要的 - 所有Spring bean都被管理 - 它们"存活"在容器内,称为"应用程序上下文".

其次,每个应用程序都有一个入口点.Web应用程序有一个Servlet,JSF使用el-resolver等.此外,还有一个应用程序上下文被引导的地方和所有bean - 自动装配.在Web应用程序中,这可以是启动侦听器.

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

应用程序上下文中的"生活"是什么?这意味着上下文实例化对象,而不是您.即 - 你永远不会new 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);

    }
}
Run Code Online (Sandbox Code Playgroud)

几点说明:

  • 在你的applicationContext.xml,你应该让<context:component-scan>这样的类被扫描了@Controller,@Service等注释.
  • Spring-MVC应用程序的入口点是DispatcherServlet,但它对您是隐藏的,因此应用程序上下文的直接交互和引导发生在场景后面.
  • UserServiceImpl也应该定义为bean - 使用<bean id=".." class="..">或使用@Service注释.由于它将是唯一的实现者UserService,它将被注入.
  • 除了@Autowired注释之外,Spring还可以使用XML可配置的自动装配.在这种情况下,所有具有与现有bean匹配的名称或类型的字段都会自动获取注入的bean.实际上,这是自动装配的最初想法 - 在没有任何配置的情况下为字段注入依赖关系.像其他的注解@Inject,@Resource也可以使用.

  • 默认范围是单例,因此您将只有一个bean实例,它在多个位置注入.如果你明确地将范围定义为"prototype",那么将存在多个实例,可能是懒惰的(取决于配置) (12认同)
  • 如果有一个被指定为"主要",它就会使用它.否则会引发异常 (7认同)
  • 是的,UserServiceImpl用Service注释,UserService是接口 (6认同)
  • 不,userService只创建一次,它在singleton-scope中 (3认同)
  • 非常感谢你的帖子,它真的为我清理了一切.关于'因为它将是唯一的实现者或UserService,它将被注入. - 如果有多个类实现Userservice怎么办?Spring如何知道它应该使用哪个实现? (2认同)

Ben*_*n J 64

取决于您是使用注释路由还是bean XML定义路由.

假设你在你的bean中定义了bean applicationContext.xml:

<beans ...>

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

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

</beans>
Run Code Online (Sandbox Code Playgroud)

应用程序启动时会发生自动装配.因此,fooController为了论证而想要使用UserServiceImpl该类,你需要注释如下:

public class FooController {

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

    // rest of class goes here
}
Run Code Online (Sandbox Code Playgroud)

当它看到时@Autowired,Spring将查找与applicationContext中的属性匹配的类,并自动注入它.如果您有多个UserService bean,那么您必须确定它应该使用哪个.

如果您执行以下操作:

UserService service = new UserServiceImpl();
Run Code Online (Sandbox Code Playgroud)

除非你自己设置,否则它不会接受@Autowired.

  • 那么在`applicationContext.xml` 中定义`bean id` 有什么用。我们将不得不使用 `UserService` 类型定义 `userService` 变量。那么为什么要在 `xml` 文件中输入。 (2认同)

小智 19

@Autowired 是Spring 2.5中引入的注释,它仅用于注入.

例如:

class A {

    private int id;

    // With setter and getter method
}

class B {

    private String name;

    @Autowired // Here we are injecting instance of Class A into class B so that you can use 'a' for accessing A's instance variables and methods.
    A a;

    // With setter and getter method

    public void showDetail() {
        System.out.println("Value of id form A class" + a.getId(););
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这不会编译,通常是不正确的.`@Autowired`并不意味着"你可以使用`A`"中`B`类中的所有函数(方法)和变量.它的作用是将"A"的实例带入"B"的实例,因此你可以从`B`做`a.getId()`. (9认同)
  • 为了更好地了解我是新手,@autowired 会使用默认构造函数实例化 A 类吗?如果不是,如果我们使用自动装配,如何在 bean 或服务中实例化值。我想如果它调用默认构造函数,为什么首先使用自动装配,只需执行 A a = new A()。请说清楚? (2认同)

jee*_*mar 9

@Autowired如何在内部工作?

前 -

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

class Greeting {
   private String message;
   //setter and getter
}
Run Code Online (Sandbox Code Playgroud)

.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>
Run Code Online (Sandbox Code Playgroud)

如果您正在使用@Autowired

class EnglishGreeting {
   @Autowired //so automatically based on the name it will identify the bean and inject.
   private Greeting greeting;
   //setter and getter
}
Run Code Online (Sandbox Code Playgroud)

.xml文件如果不使用@Autowired它看起来很相似

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

<bean id="greeting" class="com.bean.Greeting">
   <property name="message" value="Hello World"/>
</bean>
Run Code Online (Sandbox Code Playgroud)

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

@Autowired如何在内部工作?


小智 6

您只需要使用注释来注释您的服务类UserServiceImpl

@Service("userService")
Run Code Online (Sandbox Code Playgroud)

Spring容器在注册为服务时将照顾此类的生命周期。

然后,您可以在控制器中自动对其进行连线(实例化)并使用其功能:

@Autowired
UserService userService;
Run Code Online (Sandbox Code Playgroud)