控制反转
将自己new
对象的过程交给容器去做。
传统项目中,类里面主动定义需要依赖的对象,当修改下层类的时候,需要逐层往上修改其他类,耦合度太高。
而在IoC开发模式中,由Spring
管理类之间的依赖关系,降低了耦合度,减少了维护的工作量。
Demo
通过一个Demo了解IoC的做法
首先,定义一个Tool
类,里面有打印的方法
public class Tool {
public void print(){
System.out.println("Use tool to Coding");
}
}
编写实现配置管理Bean
类的Config.java
代码
@Configuration
public class Config {
@Bean("tool")
public Tool init(){
return new Tool();
}
}
编写调用Tool对象的testClass.java
类
public class TestClass {
public static void main(String[] args){
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Config.class);
Tool tool = (Tool)applicationContext.getBean("tool");
tool.print();
}
}
分析:
在main
函数里面,第一行首先根据Config
类初始化了ApplicationContext
对象,因为在Config
类中定义了名为tool的Bean,所以能够通过getBean
方法获取到Tool
类对象,并调用其print
方法。
明显区别于传统开发中的new
方法。
Tool tool = new Tool();
tool.print();
IoC原理
Bean与Spring容器
在Spring开发运行环境中,Bean可以理解成一个个具体的类。ApplicationContext
对象是具象化的Spring容器,在项目启动时,Spring容器从配置文件或配置类当中读取各种Bean依赖关系,运行时根据必要的配置创建对应的Bean类。
通用框架
SpringBoot启动类
@SpringBootApplication注解
通过Demo开始这章的学习
@SpringBootApplication
public class SpringBootApp {
public static void main(String[] args) {
SpringApplication.run(SpringBootApp.class, args);
}
}
首先需要知道@SpringBootApplication
注解包括以下三个注解:
@ComponentScan
:扫描本包下的所有路径,读取@Service
等注解标识的类到Spring容器。@Configuration
:在IoC中讲过用法,可以通过@Bean
注解往Spring容器中配置类。@EnableAutoConfiguration
:自动读取通过@Bean
注解配置好的类,并且到classpath
指定的路径读取配资好的类,将控制权教给Spring容器配置热部署
修改代码后不需要重新启动项目,在测试环境中可以更方便调试,但在生产环境,变更代码和重启服务器需要慎重,一般需要复杂的流程审批,不建议使用热部署。<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> ... </dependencies>
使用banner定制启动信息
在resouces
路径下新建banner.txt
,定义如下信息。 ```xml Application Version: Version 1.0 Spring Boot Version: ${spring-boot.version} Spring Boot formatted Version: ${spring-boot.formatted-version}
Welcome to Sprint Boot App
启动项目后可以在控制台看到如下效果<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/1123881/1653203863325-05ad424a-cba7-4583-8219-39c67afb73ba.png#clientId=u3111e7f6-7299-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=151&id=u68ca7ee4&margin=%5Bobject%20Object%5D&name=image.png&originHeight=332&originWidth=1126&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1498153&status=done&style=none&taskId=ub2e5b4a6-4c0a-4bc9-bc82-bc34b309fd6&title=&width=511.8181707248217)<br />想要关闭banner中的启动信息
```java
@SpringBootApplication
public class SpringBootApp {
public static void main(String[] args) {
//SpringApplication.run(SpringBootApp.class, args);
SpringApplication app = new SpringApplication(SpringBootApp.class);
app.setBannerMode(Banner.Mode.OFF);
app.run(args);
}
}
编写控制器
@Controller注解
往启动类所在包内,创建controller包,因为前面所说的@ComponentScan
注解,会自动扫描该包下的程序。
@RestController
public class Controller {
@RequestMapping("/index")
public String indexPage(){
return "index";
}
@RequestMapping("/welcome")
public String welcomePage(){
return "welcome";
}
}
类名随意,不影响。但需要用@RestController
注解标识。
同样在内部处理请求的方法名随意,需要用@RequestMapping
注解标识处理的url格式。
上述代码可以在访问http://localhost:8080/welcome网址后看到“welcome”输出。
@ReuqestMapping映射请求
@RequestMapping
注解用于映射url请求,有如下常用参数
- value:映射的url请求
- method:请求的Http方法,GET、POST、PUT和DELETE
-
从请求读取参数
也就是在上述params或其他方式携带的参数,在控制器中可以通过
@PathVarible
和@RequestParam
注解对应读取参数。演示代码:@RestController public class ControllerForPath { //请求里包含{id}参数 @RequestMapping(value = "/getPersonByID/{id}") public String getPersonByID(@PathVariable String id){ return "The ID is:" + id; } //请求里包含{id}和{name}参数 @RequestMapping("/getPersonByIDAndName/{id}/{name}") public String getPersonByIDAndName(@PathVariable String id,@PathVariable String name){ return "The ID is:" + id + ", name is:" + name; } //参数定义在params里 @RequestMapping(value = "/getAccountByID",params = {"id"}) public String getAccountByID(@RequestParam String id){ return "The Account ID is:" + id ; } }
注意观察上面三个请求的不同处理方式,得出结论
当参数写在url请求里时,比如
/getPersonByID/{id}
,通过@PathVariable
注解读取参数。如果通过@RequestParam
传入,比如/getAccountByID?id=1
,则需要用@RequestParam
传递参数。@PathVariable
和@RequestParam
注解都是用在参数前,所用的参数名必须和url请求携带的参数名一致,否则会报错。produces参数返回JSON格式结果
之前的demo返回的都是文本类型,有时候我们需要将输出内容转成JSON格式,对此可以使用@RequestMapping
注解的produces参数实现。
可以看到,定义了@RestController public class ControllerForJSON { @RequestMapping(value = "/demoJSON",produces = {"application/json"}) public HashMap demoJSON(){ HashMap accountHM = new HashMap(); accountHM.put("id","001"); accountHM.put("name","Peter"); accountHM.put("balance","1000"); return accountHM; } }
produces
参数,返回的account对象被自动转换成了JSON格式输出。
编写业务逻辑类
前面在控制类中处理完url请求直接就返回值了,但在真实的开发里还要往下找对应业务请求,控制类和业务类分层处理。@Service注解编写业务处理类
@Service public class AccountService { public HashMap getAccountByID(String id){ HashMap accountHM = new HashMap(); accountHM.put("ID",id); accountHM.put("balance",1500); return accountHM; } }
@RestController
public class Controller {
@Autowired
AccountService accountService;
@RequestMapping("/getAccountByID/{id}")
public HashMap getAccountByID(@PathVariable String id){
return accountService.getAccountByID(id);
}
}
- 业务逻辑类需要使用
@Service
注解修饰 - 在控制器类中,可以通过
@Autowired
注解引入业务处理类,并调用封装的业务逻辑方法
ps:面试题:@Autowired
注解和@Resource
注解的区别?
编写和读取配置文件
SpringBoot项目中,一般存放两类参数:SpringBoot服务本身相关参数:端口、工作协议等,业务有关参数:数据库配置等。配置文件一般在resources目录下,以.prperties或.yml格式。
.properties配置文件
在resoucres目录下新建application.properties配置文件
server.port=8888
db.username=sa
然后在Controller.java
控制类中进行调用
@RestController
public class Controller {
@Autowired
private Environment env;//用此对象读取参数
@RequestMapping("/getParam")
public String getParam(){
return "db.username is:" + env.getProperty("db.username");
}
}
.yml配置文件
将application.properties
文件替换为application.yml
文件
server:
port: 8888
db:
username: sa
pwd: 123
获取的方式一样,使用env.getProperty
方法读取参数
@Autowired
private Environment env;
@RequestMapping("/getYmlParam")
public String getYmlParam(){
return "db.username is:" + env.getProperty("db.username") + ", db.pwd is:" + env.getProperty("db.pwd");
}
@Value注解读取配置文件
除了使用Enviroment
对象的getProperty
方法读取配置文件的参数外,还可以通过@Value
注解读取。
@RestController
public class ControllerForValue {
//用@Value注解读取参数
@Value("${db.username}")
private String username;
@Value("${db.pwd}")
private String pwd;
@RequestMapping("/getParamFromValue")
public String getParamFromValue(){
//输出读取到的参数
return "db.username is:" + username + ", db.pwd is:" + pwd;
}
}
通过代码得知@Value注解
的用法是在括号中使用“${db.username}”
的形式读取配置文件的参数并赋予该注解修饰的变量。
参考&推荐
《搭建Spring Boot开发环境》
CSDN·IoC控制反转有什么好处?