春天的笔记
关于DI。
被称为“依赖注入”的事物。
依存是指一种关系或情况,其中一个事物或个体对另一个事物或个体产生依赖或依靠的状态。
通过使用其他类来实现(指的是)依赖性可以降低(变得松散耦合)的程度。
//Badな例
//CarクラスとEngineAクラスが蜜結合
import java.util.*;
class EngineA{
public void boot(){
System.out.println("EngineA boot");
}
public void stop(){
System.out.println("EngineA stop");
}
}
class EngineB{
public void boot(){
System.out.println("EngineB boot");
}
public void stop(){
System.out.println("EngineB stop");
}
}
class Car{
private EngineA engineA;
public Car(EngineA engineA){
this.engineA = engineA;
}
public void engineStart(){
this.engineA.boot();
}
public void engineStop(){
this.engineA.stop();
}
}
class Main {
public static void main(String[] args) throws Exception {
EngineA engineA = new EngineA();
Car car = new Car(engineA);//EngineBインスタンスを入れたい時は、Carクラス&利用クラス両方の修正が必要になる。
car.engineStart();
car.engineStop();
}
}
//Goodな例
//CarクラスとEngineAクラスが疎結合
//インターフェースにより結合度を下げる。
import java.util.*;
interface Engine{
public void boot();
public void stop();
}
class EngineA implements Engine{
public void boot(){
System.out.println("EngineA boot");
}
public void stop(){
System.out.println("EngineA stop");
}
}
class EngineB implements Engine{
public void boot(){
System.out.println("EngineB boot");
}
public void stop(){
System.out.println("EngineB stop");
}
}
class Car{
private Engine engine;
public Car(Engine engine){
this.engine = engine;
}
public void engineStart(){
this.engine.boot();
}
public void engineStop(){
this.engine.stop();
}
}
class Main {
public static void main(String[] args) throws Exception {
Engine engine = new EngineA();
Car car = new Car(engine);//EngineBインスタンスに変える場合は、利用クラスも修正だけで済む。
car.engineStart();
car.engineStop();
}
}
注入是什么?
指的是将实例放入接口的类型中。
class Main {
public static void main(String[] args) throws Exception {
Engine engineA = new EngineA();
Car car = new Car(engineA);
Engine engineB = new EngineB();
Car car = new Car(engineB);
}
}
如果想要将EngineA改成EngineA_Ver2的话,
就必须修改使用该类的实现。
如果有100个实例生成的地方,修改工作会变得非常复杂。
class EngineA_ver2 implements Engine{
public void boot(){
System.out.println("EngineA_ver2 boot");
}
public void stop(){
System.out.println("EngineA_ver2 stop");
}
}
class Main {
public static void main(String[] args) throws Exception {
//Engine engineA = new EngineA();
Engine engineA = new EngineA_ver2();
Car car = new Car(engineA);
}
}
要怎么做呢?
使用工厂。
这样当想要更换实例时,
只需要更改工厂即可。
class EngineFactory{
public static Engine CreateEngineA(){
//return new EngineA();
new EngineA_ver2();
}
public static Engine CreateEngineB(){
return new EngineB();
}
}
class Main {
public static void main(String[] args) throws Exception {
Engine engineA = EngineFactory.CreateEngineA();
Car car = new Car(engineA);
car.engineStop();
}
}
如果要实现单例模式,可以按以下方法进行。
※可能还有其他实现方法,但在此处不作讨论。
final class EngineFactory{
private static final Engine engineA = new EngineA();
private static final Engine engineB = new EngineB();
public static Engine CreateEngineA(){
return engineA;
}
public static Engine CreateEngineB(){
return engineB;
}
}
关于Spring的依赖注入。
春天已经集成了依赖注入(DI)功能。
它通过一个叫做”DI容器”的组件来实现这个功能。
该DI容器管理着被DI注入的类的实例(也被称为Bean),
并在需要时将其注入。
<DIコンテナ>
---------------------
| |
| <Bean1> |
| ----- |
| | | |
| ----- |
| |
| <Bean2> |
| ----- |
| | | |
| ----- |
| |
---------------------
常见的用法
由于Spring提供的注解(@Controller,@RestController,@Service,@Repository等等),基本上可以根据每个类的用途(例如处理事务的类应该添加@Repository注解)来标记它们作为Bean的目标,并且当需要使用时,可以添加@Autowired注解进行注入。
package com.example.demo.web.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.service.impl.HelloService;
@RestController
public class HelloController {
@Autowired
private HelloService helloService;
@GetMapping("/hello/{id:.+}")
public String hello(@PathVariable("id") int userId) {
return helloService.findOne(userId);
}
}
package com.example.demo.service.impl;
public interface HelloService {
public String findOne(int userId);
}
package com.example.demo.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.example.demo.persistence.repository.HelloRepository;
import com.example.demo.service.impl.HelloService;
@Service
public class HelloServiceImpl implements HelloService {
@Autowired
private HelloRepository helloRepository;
public String findOne( int id) {
// 1 件 検索 実行
String str = helloRepository.findOne(id);
return str;
}
}
package com.example.demo.persistence.repository;
import org.springframework.stereotype.Repository;
@Repository
public class HelloRepository {
public String findOne( int id) {
//本当はここでDBから値取ってきたりする
String[] tbl = {"yamada","yoshida"};
String str = tbl[id];
return str;
}
}

想要独自(?)定义Bean时。
有两种方法可供选择:
– 组件扫描
– 使用方法定义Bean
组件扫描
①确定要进行 Bean 化的范围(在这里指定为 demo 文件夹下)。
package com.example.demo.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = {"demo"})
public class AppConfig {
}
package com.example.demo.service;
public interface FooService{
String method();
}
想将一个类转化为Bean,可以在该类上标注”@Component”。
package com.example.demo.service.impl;
import org.springframework.stereotype.Component;
import com.example.demo.service.FooService;
@Component
public class FooServiceImpl implements FooService {
public String method() {
return "hello FooServiceImpl";
}
}
我想要一个带有@Autowired注释的Bean的设置。
package com.example.demo.web.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.service.FooService;
@RestController
public class FooController {
@Autowired
private FooService fs;
@GetMapping("/foodi")
public String fooDi() {
return fs.method();
}
}

使用方法定义的Bean定义
在`Config`类中定义一个方法来生成想要将其作为Bean的类的实例,并且加上`@Bean`注解。
这样就直接成为了一个Bean。方法的名字可以任意取。
package com.example.demo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.example.demo.service.HogeService;
import com.example.demo.service.impl.HogeServiceImpl;
@Configuration
public class AppConfig2 {
@Bean
public HogeService getHogeService() {
return new HogeServiceImpl();
}
}
package com.example.demo.service;
public interface HogeService{
public String method();
}
package com.example.demo.service.impl;
import com.example.demo.service.HogeService;
public class HogeServiceImpl implements HogeService {
public HogeServiceImpl() {
}
public String method() {
return "hello HogeServiceImpl";
}
}
package com.example.demo.web.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.service.HogeService;
@RestController
public class HogeController {
private HogeService hs;
@Autowired //アノテーションはコンストラクタが単一なら省略可能
public HogeController(HogeService hs) {
this.hs = hs;
}
@GetMapping("/hogedi")
public String hogeDi() {
return hs.method();
}
}

文献引用
“4章 DI(依存性注入)的概念是什么”
https://www.slideshare.net/masatoshitada7/spring-boot-jjug 的第二页展示了Spring的核心概念,包括”DI”、”容器”和”Bean”。