Answers:
首先,也是最重要的-所有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);
}
}
一些注意事项:
applicationContext.xml
,你应该让<context:component-scan>
这样的类被扫描了@Controller
,@Service
等注释。UserServiceImpl
还应该定义为bean-使用<bean id=".." class="..">
或使用@Service
注释。由于它将是的唯一实现者UserService
,因此它将被注入。@Autowired
注释之外,Spring可以使用XML可配置的自动装配。在这种情况下,具有与现有Bean匹配的名称或类型的所有字段都会自动注入Bean。实际上,这是自动装配的最初想法-在没有任何配置的情况下注入带有依赖项的字段。其他注释一样@Inject
,@Resource
也可以使用。取决于您是要注解路由还是bean XML定义路由。
假设您在applicationContext.xml
:中定义了bean :
<beans ...>
<bean id="userService" class="com.foo.UserServiceImpl"/>
<bean id="fooController" class="com.foo.FooController"/>
</beans>
自动装配发生在应用程序启动时。因此,在中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
然后自动将其注入。如果您有一个以上的UserService
bean,则必须确定应使用哪个bean。
如果您执行以下操作:
UserService service = new UserServiceImpl();
@Autowired
除非您自行设置,否则它将不会拾取。
bean id
在applicationContext.xml
。我们将不得不userService
用UserService
类型定义变量。那么为什么要在xml
文件中输入。
@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(););
}
}
@Autowired
并不意味着“你可以使用所有的功能(方法)和变量B
类从类A
”。它所做的是将的实例A
引入的实例B
,因此您可以a.getId()
从中进行B
。
@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>
如果仍有疑问,请通过下面的现场演示进行
您只需要使用注释来注释您的服务类UserServiceImpl
:
@Service("userService")
Spring容器在注册为服务时将照顾此类的生命周期。
然后,您可以在控制器中自动对其进行连线(实例化)并使用其功能:
@Autowired
UserService userService;
Spring依赖注入有助于您消除类的耦合。而不是像这样创建对象:
UserService userService = new UserServiceImpl();
介绍DI后,您将使用此功能:
@Autowired
private UserService userService;
为此,您需要在ServiceConfiguration
文件中创建服务的bean 。之后,您需要将该ServiceConfiguration
类导入到您的WebApplicationConfiguration
类中,以便您可以像下面这样将bean自动装配到Controller中:
public class AccController {
@Autowired
private UserService userService;
}
您可以在这里找到一个Java配置基于POC 例子。
标准方式:
@RestController
public class Main {
UserService userService;
public Main(){
userService = new UserServiceImpl();
}
@GetMapping("/")
public String index(){
return userService.print("Example test");
}
}
用户服务界面:
public interface UserService {
String print(String text);
}
UserServiceImpl类:
public class UserServiceImpl implements UserService {
@Override
public String print(String text) {
return text + " UserServiceImpl";
}
}
输出: Example test UserServiceImpl
那是紧密耦合类的一个很好的例子,糟糕的设计例子,并且测试会有问题(PowerMockito也很糟糕)。
现在让我们看一下SpringBoot依赖注入,这是松耦合的好例子:
界面保持不变,
主班:
@RestController
public class Main {
UserService userService;
@Autowired
public Main(UserService userService){
this.userService = userService;
}
@GetMapping("/")
public String index(){
return userService.print("Example test");
}
}
ServiceUserImpl类:
@Component
public class UserServiceImpl implements UserService {
@Override
public String print(String text) {
return text + " UserServiceImpl";
}
}
输出: Example test UserServiceImpl
现在很容易编写测试:
@RunWith(MockitoJUnitRunner.class)
public class MainTest {
@Mock
UserService userService;
@Test
public void indexTest() {
when(userService.print("Example test")).thenReturn("Example test UserServiceImpl");
String result = new Main(userService).index();
assertEquals(result, "Example test UserServiceImpl");
}
}
我@Autowired
在构造函数上显示了注释,但也可以在setter或field上使用它。
请记住,必须@Autowired
通过将元素添加<context:annotation-config/>
到spring配置文件中来启用注释。这将注册AutowiredAnnotationBeanPostProcessor
,并注意注释的处理。
然后,您可以使用现场注入方法自动为服务布线。
public class YourController{
@Autowired
private UserService userService;
}
我从Spring @autowired注解中找到了这个
您可以使用3种方法来创建实例@Autowired
。
1. @Autowired
关于属性
注释可以直接在属性上使用,因此无需使用getter和setter:
@Component("userService")
public class UserService {
public String getName() {
return "service name";
}
}
@Component
public class UserController {
@Autowired
UserService userService
}
在上面的例子中,春季查找并注入userService
时UserController
创建。
2. @Autowired
在二传手
该@Autowired
批注可在setter方法中使用。在下面的示例中,在setter方法上使用注释时,将使用userService
when UserController
创建实例调用setter方法:
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;
}
}
用简单的话说自动装配,即自动连接链接,这是一个问题,由谁进行接线以及哪种接线。答案是:容器可以做到这一点,并且支持辅助类型的接线,基元需要手动完成。
问题:集装箱如何知道哪种类型的接线?
答:我们将其定义为byType,byName,constructor。
问题:有什么方法可以不定义自动布线的类型?
答:是的,只需做一个注释即可,@ Autowired。
问题:但是系统如何知道,我需要选择此类辅助数据?
答:您可以在spring.xml文件中或通过对类使用构造型注释来提供数据,以便容器自己可以为您创建对象。