关于Spring Boot学习的注入问题
依赖注入(DI)
依赖注入(Dependency Injection)是一种软件模式,旨在通过外部配置文件等方式,将对象注入并从程序的源代码中排除组件之间的依赖关系。这个模式通常用DI来缩写,取自英文的首字母。
这是一种软件模式,它从程序源代码中排除了组件间的依赖关系,并允许在运行时通过外部配置文件等方式进行注入。此处所指的组件可以替换为类。
对某物或某人有依赖或依赖性
当在类A中实例化类B时,类A不能在没有类B的情况下运行。这种状态可以说是类A和类B存在依赖关系。用代码表示如下:
public class ClassA {
public static void main(String... args) {
ClassB classB = new ClassB();
System.out.println(classB.execute());
}
}
public class ClassB {
public execute() {
System.out.println("ClassB::execute()");
}
}
灌输
不是直接进行new操作,而是将设置等内容保存在外部文件中,在运行时分配指定类的实例。这个功能被称为依赖注入容器(DI容器)。
春天有这个DI容器,所以在设定好之后,它会在运行时帮我们注入实例。
Spring Boot的依赖注入(DI)
为了在Spring的DI容器中注册为bean,我们使用Spring注解。
以下注解的作用都是相同的,因此可以根据名称选择使用。
@Service
サービス層に配置@Repository
データ層に配置@Controller
コントローラ層に配置@Component
その他在将类注册到DI容器后,可以使用注入。
注入可以通过注释进行表示,以下是注入的几种方式。
@Autowired
org.springframework.bean.factory@Inject
javax.inject@Resource
javax.annotation由于操作不变,我们将在这里使用@Autowired。
被@Autowired指定的实例将被注入。
@Autowired的用法
准备
我将创建一个用于注入的方法。由于我想要进行替换,所以我将使用接口。
left to right direction
interface ICommand {
void execute()
}
class FirstCommand
FirstCommand --|> ICommand
SecondCommand --|> ICommand
构造函数注入
在构造函数上添加@Autowired。
这种方法是Spring团队推荐的方法,它的优点是字段可以设置为final,并且可以在构造函数中指定其他实例。
@Slf4j
@Service
public class ConstructorAutowiredService {
private final IComponent component;
@Autowired
public ConstructorAutowiredService(IComponent secondComponent) {
this.component = secondComponent;
}
@PostConstruct
public void execute() {
log.info("execute()");
this.component.execute();
}
}
通过将构造函数的参数名(在这里是secondComponent)设置为类名的小驼峰命名法,自动注入SecondComponent。
将这里设置为firstComponent,注入FirstComponent。
为了使ConstructorAutowiredService.java更容易理解,我们创建了一个构造函数并在其上添加了@Autowired。但为了更简洁地编写代码,我们将使用带有final字段的构造函数参数的注解@RequiredArgsConstructor。
@Slf4j
@RequiredArgsConstructor
@Service
public class RequiredArgsConstructorService {
// @RequiredArgsConstructorを使った場合は@Autowiredは省略できる
private final IComponent firstComponent;
// もちろんConstructorも省略できる
@PostConstruct
public void execute() {
log.info("execute()");
this.firstComponent.execute();
}
}
用这种写法,可以省略@Autowired和构造函数。
注入攻击
在字段上加上@Autowired注释是一种简洁明了的方法。
@Slf4j
@Service
public class FirstComponentService {
@Autowired
private IComponent firstComponent;
@PostConstruct
public void execute() {
log.info("execute()");
this.firstComponent.execute();
}
}
@Slf4j
@Service
public class SecondComponentService {
@Autowired
private IComponent secondComponent;
@PostConstruct
public void execute() {
log.info("execute()");
this.secondComponent.execute();
}
}
在注入类的定位方面,与构造函数注入类似,依靠的是类的名称。
引擎注入
如其名,@Autowired用于Setter。
由于找不到合适的使用场景,所以没有示例。
使用配置进行设置。
我们已经看到了基本的方法,但是尽管称之为依赖注入,但字段名称与类名称相关联并且不方便使用。
因此,我们将提供一种通过指定名称来注入实例的方法。
Configuration用于定义Bean。换句话说,它设置了在DI容器中使用哪个实例以及初始值的注入方式。
Configuration可以通过以下方式进行设置:
– 配置文件(xml)
– 类
– 注解
这个是可设定的,但是在这里我们会用注释完成。
创建@Configuration类
在Configuration类上添加@Configuration注解。
在方法上添加@Bean注解。可以带参数以便进行区分。
尽管这里只是简单地执行了new操作,但从写法可以看出,在此可以对实例进行值的设置。
@Configuration
public class App {
@Bean("component1")
public IComponent getComponent1() {
return new FirstComponent();
}
@Bean("component2")
public IComponent getComponent2() {
return new SecondComponent();
}
}
使用配置
我将使用Configuration中设置的Bean进行注入。在这个例子中,我将演示构造函数注入。
@Slf4j
@Service
public class UsinAppConfigService {
private final IComponent component;
@Autowired
public UsinAppConfigService(@Qualifier("component1") IComponent component) {
this.component = component;
}
@PostConstruct
public void execute() {
log.info("service executed");
this.component.execute();
}
}
要指定名字获取Bean,需要使用@Qualifier注解。
@Qualifier与@Autowired一起使用。
在构造函数的参数中使用@Qualifier指定名字。
执行时,将执行FirstComponent。
总结
由于可以将其作为存根进行单元测试,因此它看起来对开发非常有用。
例如,RestTemplate在URL中查询JSON并返回,但是我们是否可以注入并返回固定的JSON呢?
在商业领域中,策略模式是开发必需且有用的功能。我们希望能够利用现有的DI容器,提高开发速度。
请提供参考资料。
关于依存性注入(DI):
关于@Component、@Service、@Repository、@Controller的区别:
关于@Autowired、@Inject、@Resource的区别的验证