自动assembly在spring如何工作?
对于Spring
的控制反转 ( IoC
)是如何工作的,我有点困惑。
假设我有一个名为UserServiceImpl
的服务类实现了UserService
接口。
这将是@Autowired
?
在我的Controllers
操作中,我将如何instantiate
此服务的一个instance
?
我会做下面的事吗?
UserService userService = new UserServiceImpl();
首先,也是最重要的 – 所有的Spring bean都被pipe理 – 它们“活在”一个容器内,称为“应用程序上下文”。
其次,每个应用程序都有一个入口点。 Web应用程序有一个Servlet, JSF使用elparsing器等等。另外,还有一个地方是应用程序上下文被引导,所有的bean都是自动assembly的。 在Web应用程序中,这可以是一个启动监听器。
自动assembly通过将一个bean的实例放入另一个bean实例的所需字段中来实现。 这两个类都应该是bean,也就是说,它们应该被定义为生存在应用程序上下文中。
什么是应用程序环境中的“生活”? 这意味着上下文实例化对象,而不是你。 也就是说,你永远不会创buildnew UserServiceImpl()
– 容器find每个注入点并在那里设置一个实例。
在你的控制器中,你只需要:
@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); } }
一些注意事项:
- 在您的
applicationContext.xml
您应该启用<context:component-scan>
以便<context:component-scan>
类的@Controller
,@Service
@Controller
等注释。 - Spring-MVC应用程序的入口点是DispatcherServlet,但它对您来说是隐藏的,因此应用程序上下文的直接交互和引导发生在场景后面。
-
UserServiceImpl
也应该被定义为bean – 使用<bean id=".." class="..">
或使用@Service
注释。 由于它将是UserService
的唯一实现者,因此将被注入。 - 除了
@Autowired
注解,Spring可以使用XMLconfiguration的自动assembly。 在这种情况下,具有与现有bean相匹配的名称或types的所有字段将自动获取注入的bean。 实际上,这是自动assembly的最初想法 – 在没有任何configuration的情况下使用依赖关系注入字段。 其他注释(如@@Inject
,@Resource
也可以使用。
取决于你是去注释path还是bean的XML定义路线。
假定你的applicationContext.xml
定义了bean:
<beans ...> <bean id="userService" class="com.foo.UserServiceImpl"/> <bean id="fooController" class="com.foo.FooController"/> </beans>
自动assembly发生在应用程序启动时。 所以,在fooController
,为了参数的fooController
,想要使用UserServiceImpl
类,你可以按照下面的方式对它进行注释:
public class FooController { // You could also annotate the setUserService method instead of this @Autowired private UserService userService; // rest of class goes here }
当它看到@Autowired
,Spring将查找一个匹配applicationContext中的属性的类,并自动注入它。 如果你有超过1个UserService bean,那么你将不得不限定它应该使用哪一个。
如果您执行以下操作:
UserService service = new UserServiceImpl();
除非你自己设置@Autowired,否则它将不会起作用。
@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; private int roll; // With setter and getter method public void showDetail() { System.out.println("Value of id form A class" + a.getId();); } }
@Autowired
-
将构造函数,字段,setter方法或configuration方法标记为由Spring的dependency injection工具自动assembly。
-
任何给定的bean类只有一个构造函数(max)可以携带这个注解,指示构造函数在用作Spring bean时自动assembly。 这样的构造不必公开。
-
在调用任何configuration方法之前,在构buildbean之后立即注入字段。 这样的configuration字段不必公开。
-
configuration方法可以有任意的名字和任意数量的参数; 每个参数都将在Spring容器中使用匹配的bean进行自动assembly。 Bean属性setter方法实际上只是这种通用configuration方法的特例。 这种configuration方法不必公开。
-
在多参数方法的情况下,“required”参数适用于所有参数。
-
在Collection或Map依赖types的情况下,容器将自动装载符合声明值types的所有bean。 在Map的情况下,键必须声明为Stringtypes,并将parsing为相应的bean名称。
@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如何在内部工作?
你只需要用注解来注释你的服务类UserServiceImpl
@Service("userService")
Spring容器将注意到这个类的生命周期,因为它注册为服务。
然后在你的控制器中,你可以自动连线(实例化)并使用它的function。
@Autowired UserService userService;
Springdependency injection可以帮助你从类中移除耦合。 而不是像这样创build对象
UserService userService = new UserServiceImpl();
介绍DI之后,您将使用这个
@Autowired private UserService userService;
为了达到这个目的,你需要在你的ServiceConfiguration文件中创build一个服务的bean。 之后,您需要将该ServiceConfiguration类导入到您的WebApplicationConfiguration类中,以便您可以像这样将该Autowire bean插入到您的Controller中。
public class AccController { @Autowired private UserService userService; }
你可以在这里find一个基于javaconfiguration的POC 例子
控制反转的整个概念意味着你不需要手动实例化对象,并提供所有必要的依赖关系。 当你使用适当的注解来注释类时(例如@Service
),Spring会自动为你实例化对象。 如果您不熟悉注释,则也可以使用XML文件。 但是,当您不想加载整个spring上下文时,在unit testing中手动实例化类(使用new
关键字)并不是一个坏主意。
请记住,您必须通过在springconfiguration文件中添加元素<context:annotation-config/>
来启用@Autowired注释。 这将注册AutowiredAnnotationBeanPostProcessor,它负责注释的处理。
然后,您可以使用字段注入方法自动装载您的服务。
public class YourController{ @Autowired private UserService userService; }
我从Spring的@autowired注释中find了这个