一、配置Maven
在pom文件中添加依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-parent</artifactId>
<version>2.6.6</version>
</parent>
<groupId>com.easy</groupId>
<artifactId>EasySpringA</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
</dependencies>
</project>
二、项目启动类
运行该类就运行了整个项目
在类名上添加注解@SpringBootApplication用于标记主配置类,并自动配置 Spring Boot 应用程序。
package com.easy;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class EasySpringAApplication {
//项目启动类 运行该类就运行了整个项目
public static void main(String[] args) {
SpringApplication.run(EasySpringAApplication.class,args);
}
}
SpringApplication.run()
方法用于启动 Spring Boot 应用程序。它接受两个参数:- 第一个参数是要启动的应用程序的主类,即
EasySpringAApplication.class
。 - 第二个参数是命令行参数数组
args
,这些参数可以用来向应用程序传递命令行选项。
三、IOC 控制反转
容器:IOC
Spring 通过IOC容器来管理所有Java对象的实例化和初始化,控制对象与对象之间的依赖关系。我们将有IOC容器管理的Java对象成为Spring Bean,它与使用关键字new创建的对象没有任何区别.
容器和代码之间的控制权反转,代码中不需要明文调用法来得到对象,只需要声明我们需要什么对象即可
反转
将对象的创建权利交出去,将对象和对象之间关系的维护权交出去,交给第三方容器负责。
容器中放Bean对象,使用map集合
通过BeanFactory工厂加反射实例化对象,然后进行初始化得到最终对象
BeanFactory:这是IOC容器的基本实现,是Spring内部使用的接口
依赖注入
DI:依赖注入实现了控制反转的思想
指的是应用程序在运行时依赖IOC容器来动态注入组件所需要的某个依赖对象,Spring的DI具体就是通过反射实现注入的,反射允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性等。
示例:
该类中需要EasyService类的对象,在这个类中只需要声明我们依赖EasyService这个类就可以,而不需要通过代码来主动获取EasyService类的对象
package com.easy.controller;
import com.easy.common.TestA;
import com.easy.service.EasyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
//@Scope(value = "request")
public class EasyController {
//该类中需要EasyService类的对象
//在这个类中只需要声明我们依赖EasyService这个类就可以
//而不需要通过代码来主动获取EasyService类的对象
//依赖注入DI 通过识别依赖关系注入对应的对象
@Autowired
EasyService easyS;
@Autowired
TestA testa;
@RequestMapping("testb")
public String testB(){
testa.test();
return "Easy method";
}
@RequestMapping("easya")
public String easya(){
System.out.println(easyS);
return "new Service";
}
@RequestMapping("hello")
public String hello(){
return "java so easy";
}
}
我们只需要声明一个EasyService类的对象,然后利用@Autowired注解来对该对象进行实例化。
注解
格式:@注解名称(属性1=属性值)
可以使用在类上面、属性上面、方法上面
常用的注解:
1. 组件扫描注解
@Controller:用于Web层,标识一个类为控制器组件,处理HTTP请求。
@RestController:组合了@Controller和@ResponseBody,用于RESTful Web服务,方法返回值直接作为响应体。
@Service:用于业务逻辑层,标识一个类为服务层组件,处理业务逻辑。
@Repository:用于数据访问层(DAO),标识一个类为持久层组件,处理数据访问。
@Component:通用组件注解,标识一个类为Spring组件,适用于其他功能类。
2. 配置注解
@Bean:在配置类中使用,定义一个Spring Bean。
@Configuration:标识一个类为配置类,包含Spring Bean的定义。
3. 其他常用注解
@Autowired:自动装配Bean,按类型注入。
@Qualifier:与@Autowired一起使用,按名称注入。
@Value:注入配置文件中的属性值。
@Scope:定义Bean的作用域,如单例(singleton)或原型(prototype)。
@PostConstruct:在Bean初始化后执行的方法。
@PreDestroy:在Bean销毁前执行的方法。
@RequestMapping:映射HTTP请求到控制器方法。
@GetMapping、@PostMapping、@PutMapping、@DeleteMapping:分别映射GET、POST、PUT、DELETE请求。
@RequestParam:绑定请求参数到方法参数。
@PathVariable:绑定URL路径变量到方法参数。
@RequestBody:绑定请求体到方法参数。
@ResponseBody:将方法返回值作为响应体。
@Transactional:声明式事务管理,标识一个方法或类需要事务支持。
示例:
@RequestMapping("名字")将地址映射成方法,执行和代码后,在浏览器中输入该名字作为地址即可访问。
在EasyController类中定义了一个方法,上面注解为@RequestMapping("hello")
运行代码,在浏览器上输入http://localhost:8080/hello 就能看到方法的返回值
@RequestMapping("hello")
public String hello(){
return "java so easy";
}
Bean的作用域
singleton 单例模式 一个对象 默认 prototype 原型模式 每次需要都来一个新的对象 request web项目中请求作用域 每次请求都会创建一个新的对象 session 每次会话都会创建一个新的对象 GlobalSession 全局的
下面是示例
在TestA类中定义一个test方法,用来返回调用对象的地址
@Component
public class TestA {
public void test(){
System.out.println(this);
System.out.println("test method");
}
}
singleton 单例模式 一个对象 默认
在EasyController类和EasyAController中分别声明上类的对象并使用注解为其实例化,
@Autowired
TestA testa;
@RequestMapping("testb")
public String testB(){
testa.test();
return "Easy method";
}
@RestController
public class EasyAController {
@Autowired
TestA testa;
@RequestMapping("testa")
public String testA(){
testa.test();
return "EasyA method";
}
}
执行代码后,分别输入各自的网址进行访问,查看日志
发现对象的地址是相同的,所以在未声明Bean的作用域时,默认是单例模式,只有一个对象
prototype 原型模式 每次需要都来一个新的对象
在上述实例TestA类上面利用@Scope声明Bean的作用域为prototype
@Scope(value= ConfigurableBeanFactory.SCOPE_PROTOTYPE)
//@Scope(value = "request")
@Component
public class TestA {
public void test(){
System.out.println(this);
System.out.println("test method");
}
}
然后再次执行上面的操作,得到的日志是
两个的对象地址不同,所以每次都需要一个新的对象
request web项目中请求作用域 每次请求都会创建一个新的对象
在EasyController类和EasyAController类上都定义Bean的作用域
@Scope(value = "request")
@RestController
public class EasyAController {
@Autowired
TestA testa;
@RequestMapping("testa")
public String testA(){
testa.test();
return "EasyA method";
}
}
执行上面的操作,打印的日志为
注意:@Service注解是不能代替@Controller,@Service无法处理http请求
Bean的生命周期
创建EasyBean类
1)根据配置情况调用 Bean 构造方法或工厂方法实例化 Bean。
2)利用依赖注入完成 Bean 中所有属性值的配置注入。
3) 如果 Bean 实现了 BeanNameAware 接口,则 Spring 调用 Bean 的 setBeanName() 方法传入当前 Bean 的 id 值。
4)如果 Bean 实现了 BeanFactoryAware 接口,则 Spring 调用 setBeanFactory() 方法传入当前工厂实例的引用。
5) 当一个 Bean 实现了 ApplicationContextAware 接口并在 Spring 容器中被实例化时,Spring 容器会自动调用该 Bean 的 setApplicationContext 方法,并将应用程序上下文ApplicationContext作为参数传递进来
6)BeanPostProcessor 是 Spring 框架中的一个重要接口,它允许开发者在 Spring 容器创建和初始化 bean 的过程中,对 bean 进行自定义处理。这包括在 bean 实例化之后、属性设置之前(postProcessBeforeInitialization 方法),以及在 bean 初始化之后(postProcessAfterInitialization 方法)执行自定义逻辑
Spring 容器在创建和初始化每一个 bean 时,都会调用 CustomBeanPostProcessor 中的这两个方法,允许你进行自定义处理
创建一个EasyBeanProcesser类实现BeanPostProcessor接口
7)InitializingBean 是 Spring 框架中的一个接口,它定义了一个 afterPropertiesSet 方法。当 Spring 容器创建 bean 的所有属性都被设置完成后,会调用这个方法。
8)如果在配置文件中通过 init-method 属性指定了初始化方法,则调用该初始化方法。
创建一个EasyConfig类
9)如果 BeanPostProcessor 和 Bean 关联,则 Spring 将调用该接口的初始化方法 postProcessAfterInitialization()。此时,Bean 已经可以被应用系统使用了。
10)如果在 <bean> 中指定了该 Bean 的作用范围为 scope="singleton",则将该 Bean 放入 Spring IoC 的缓存池中,将触发 Spring 对该 Bean 的生命周期管理;如果在 <bean> 中指定了该 Bean 的作用范围为 scope="prototype",则将该 Bean 交给调用者,调用者管理该 Bean 的生命周期,Spring 不再管理该 Bean。
11)如果 Bean 实现了 DisposableBean 接口,则 Spring 会调用 destory() 方法将 Spring 中的 Bean 销毁;如果在配置文件中通过 destory-method 属性指定了 Bean 的销毁方法,则 Spring 将调用该方法对 Bean 进行销毁
下面是完整代码以及执行时打印的日志
package com.easy.common;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
//@Component("easybean")
public class EasyBean implements BeanNameAware , BeanFactoryAware, ApplicationContextAware, InitializingBean , DisposableBean {
public EasyBean(){
System.out.println("1---构造方法");
}
public void init(){
System.out.println("8---init Method");
}
TestA testa;
@Autowired
public void setTesta(TestA testa){
System.out.println("2---注入属性");
this.testa=testa;
}
@Override
public void setBeanName(String name) {
System.out.println("3---BeanNameAware接口的 setBeanName方法"+name);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("4---BeanFactoryAware接口的setBeanFactory方法"+beanFactory);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("5---ApplicationContextAware接口的setApplicationContext方法"+applicationContext);
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("7---InitializingBean接口的afterPropertiesSet方法");
}
@Override
public void destroy() throws Exception {
System.out.println("easybean被回收了");
}
}