目录
1 什么是Spring?
我们通常所说的 Spring 指的是 Spring Framework(Spring 框架),它是一个开源框架,有着活跃而庞大的用户社区,Spring为我们提供了一系列的功能和工具,使得java程序的开发更简单,高效,可维护。而且Spring 支持广泛的应用场景,它可以让 Java 企业级的应用程序开发起来更简单。
用一句话概括Spring 是包含了众多工具方法的 IoC容器。
1.1 什么是容器?
容器是用来存储某种物品的装置,比如List/Map是数据存储容器,Tomcat是Web容器,Spring也是一个容器,而且Spring是一个IoC容器。
1.2 IoC是什么?为什么说Spring是IoC容器?
IoC(Inversion of Control)意为控制反转,IoC是面向对象编程中的一种设计原则,主要通过第三方IoC容器对Bean对象进行统一管理,以及组织对象之间的依赖关系,获得依赖对象的过程,由原本程序自己控制,变为了由IoC容器来主动注入,控制权发生了反转
简单陈述一下就是,在传统的java代码中,A类如果要使用B类的对象的话,需要在代码中调用B类的构造方法,然而在Spring框架中,我们会先把B类注册到Spring容器中,根据规则在规定时机创建一个B类的对象,这个对象被称为Bean对象,如果A类要使用B类的对象时,我们会使用Spring容器把Bean对象注入到A类对B类对象的引用中,即是完成了控制反转。
Spring容器主要是对IoC设计模式的实现,因此Spring被称为IoC容器
1.3 IoC和DI的理解
IoC意为控制反转,上文已经解释过就不再阐述,但是DI是什么呢?
DI意为依赖注入,其实IoC和DI说的是同一件事,只是角度不同而已,DI实际上是IoC的方法实现,依赖注入就是由IoC容器在运行过程中动态地将某种依赖关系注入对象之中,IoC的关注角度是控制权的变换,DI则更关注依赖的注入
实现方式:
DI是IoC的实现方法之一,而DI的实现方法主要有两种,属性注入和构造注入
实现原理:
主要依靠反射和ASM字节码框架实现(字节码框架相比反射更高效,更强大)
2,Spring的创建使用
2.1 创建Spring项目
首先打开IDEA新建项目
根据步骤进行选择
1 项目框架选择Spring
Spring Initializer 是一个用于创建和初始化 Spring 项目的Web界面或命令行工具。它提供了一个简单易用的界面,让开发人员可以快速生成和配置基于 Spring 的项目结构,并且可以选择添加额外的依赖、配置文件和其他项目设置。
2 编程语言选择Java
3 项目类型选择Maven,方便我们管理项目
4 选择自己的JDK
5 选择Java版本和JDK对应
SpringBoot版本要和Java版本对应,我的JDK1.8只能选择2.7版本的,如果大家创建项目的时候需要去查询JDK版本对应的SpringBoot版本,SpringBoot版本3以上需要选择JDK17,JDK1.8会报错
创建时需要加载很多资源因此可能会需要一点时间,请不要着急
创建完毕
2.2 Spring框架的使用
2.2.1 Spring容器Bean对象的注册方式
类注解注册(为本类进行注册,默认单例)
@Configuration(配置存储)
@Configuration
public class AppConfig {
}
@Controller(控制器存储)
@Controller
public class Cont {
@Autowired
Serv serv ;
}
@Service(服务存储)
@Service
public class Serv {
@Autowired
Repo repo;
}
@Repository(仓库存储)
@Repository
public class Repo {
User user = new User();
}
@Component(组件存储)
方法注解注册(为本方法进行注册,默认单例)
@Bean 方法注册,可以注册多个
@Configuration
public class AppConfig {
//如果当前类是容器管理的Bean对象
//方法上使用@Bean注解,就可以把方法返回值,注册到容器中
//祖册方式是key==方法名,value==方法值
@Bean
public Person p1(){
return new Person();
}
@Bean
public Person p2(){
return new Person();
}
//添加多个Mobile对象,然后需要在Person中注入指定的某一个
@Bean
public Mobile m1(){
Mobile m = new Mobile();
m.setName("华为");
return m;
}
@Bean
public Mobile m2(){
Mobile m = new Mobile();
m.setName("苹果");
return m;
}
}
方法注解注册实际上是注册的是返回值的Bean对象
2.2.2 Bean对象的注入方式
@Autowired 注入对象,使用在属性中 Spring提供,必须在Spring框架中使用(否则报错),
@Resourse 后可跟(name="user")改变注入对象名,JDK提供但不实现,具体由框架实现,可以不在Spring框架中使用
两个注解显示指定引用某个Bean,使用方式不同,@Resourse(name="xxx") @Autowired配合@qualifier("")使用
2.2.3 其他注解的使用
@Data 自动生成属性的get/set,equals/hashCode,toString方法
@qualifier("")配合Resourse使用,用来改变注入对象名
3 运行Spring项目
Mobile类
@Component
@Data
public class Mobile {
private String name;
}
AppConfig类
@Configuration
public class AppConfig {
//如果当前类是容器管理的Bean对象
//方法上使用@Bean注解,就可以把方法返回值,注册到容器中
//祖册方式是key==方法名,value==方法值
@Bean
public Person p1(){
return new Person();
}
@Bean
public Person p2(){
return new Person();
}
//添加多个Mobile对象,然后需要在Person中注入指定的某一个
@Bean
public Mobile m1(){
Mobile m = new Mobile();
m.setName("华为");
return m;
}
@Bean
public Mobile m2(){
Mobile m = new Mobile();
m.setName("苹果");
return m;
}
}
Person类
@Component
@Data // 这是lombok注解,可以自动生成属性的get/set,equals/hashCode,toString方法
public class Person {
@Autowired //
private Mobile mobile;
//不使用lombok的话需要创建get,set方法
@Autowired
private Mobile m2;
@Autowired
@Qualifier("m2")
private Mobile m;
@Resource
private Mobile m1;
@Resource(name="m1")
private Mobile mm;
}
启动类:
public class Main {
public static void main(String[] args) {
//创建一个容器 类似List
//Annotation是注解,ApplicationContext是上下文环境
//new出来是一个注解配置的容器,传入的参数是需要扫描的包路径
//含义:在指定的包路径之下进行扫描,如果是Spring框架注解的类,就会注册到容器中
ApplicationContext context = new AnnotationConfigApplicationContext("要扫描的包路径");
//使用context.getBean("类名(首字母小写)")来把对应Bean对象注入引用
Person p = (Person) context.getBean("person");
Mobile mobile = (Mobile) context.getBean("mobile");
System.out.println(p);
System.out.println("===person[m2]: "+p.getM2());
//打印person的mobile属性,验证是否为容器注入的mobile
System.out.println("===person[mobile]: "+p.getMobile());
System.out.println("===person[m]: "+p.getM());
System.out.println("===person[m1]: "+p.getM1());
System.out.println("===person[mm]: "+p.getMm());
System.out.println(mobile);
Person p1 = (Person) context.getBean("p1");
System.out.println(p1);
System.out.println(p==p1);
Person p2 = (Person) context.getBean("p2");
System.out.println(p2);
System.out.println(p1==p2);
}
}
演示过程:要扫描的包路径作为参数输入AnnotationConfigApplicationContext的构造方法中,程序启动之后就会对输入的包路径进行扫描,把需要注解注册的类和方法注册Bean对象
p引用指向的是是由Person类注解注册的bean对象,mobile注入了Mobile类的Bean对象,m2是AppConfig类中的m2方法注册的Bean对象,m被@qualifier改变注入的对象名指向了m2方法注册的Bean对象,同理,m1指向m1方法注册的Bean对象,mm被改变注入的对象名指向了m1方法注册的Bean对象
返回的结果: