对于Spring中的控制反转(IoC)是如何工作的,我有点困惑。
假设我有一个名为UserServiceImpl的服务类,它实现了UserService接口。
@Autowired会怎么做?
在我的控制器中,我如何实例化这个服务的实例?
我能做下面的事情吗?
UserService userService = new UserServiceImpl();
对于Spring中的控制反转(IoC)是如何工作的,我有点困惑。
假设我有一个名为UserServiceImpl的服务类,它实现了UserService接口。
@Autowired会怎么做?
在我的控制器中,我如何实例化这个服务的实例?
我能做下面的事情吗?
UserService userService = new UserServiceImpl();
当前回答
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关键字)并不是一个坏主意。
你只需要用annotation注释你的服务类UserServiceImpl:
@Service("userService")
Spring容器将在该类注册为服务时负责其生命周期。
然后在你的控制器中,你可以自动连接(实例化)它并使用它的功能:
@Autowired
UserService userService;
@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(););
}
}
标准方法:
@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";
}
}
输出:示例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";
}
}
输出:示例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。
请记住,您必须通过在spring配置文件中添加元素<context:annotation-config/>来启用@Autowired注释。这将注册AutowiredAnnotationBeanPostProcessor,它负责处理注释。
然后,您可以使用字段注入方法自动装配您的服务。
public class YourController{
@Autowired
private UserService userService;
}
我从Spring @autowired注释中找到了这个