Spring 是包含了众多⼯具方法的 IoC 容器(控制反转容器)
Spring 是⼀个 IoC 容器, 说的就是将对象的创建和销毁的权利都交给 Spring 来管理了, 它本身又具备了存储对象和获取对象的能力
说到 IoC 不得不提的⼀个词就是 “DI”
IoC和DI的区别
图示Spring的创建和使用
使⽤ Maven ⽅式来创建⼀个 Spring 项⽬分为3步
首先选择New --> Project 新建一个Maven项目.
选择Maven 后 点击Next 即可.不需要勾选任何添加.
选择项目要创建的目录,并更改项目名称
在pom.xml中添加依赖并刷新依赖.等待右下角进度条下载完成即可.
下面是我导入的依赖.大家也可以在中央仓库中搜索依赖并添加.
<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>5.2.3.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-beansartifactId>
<version>5.2.3.RELEASEversion>
dependency>
dependencies>
在src->main->java 目录下.创建启动类 名称可以自定义.
在启动类中添加main方法即可.
这样,我们的Spring项目就创建好了.
所谓的 Bean 就是 Java 语⾔中的⼀个普通对象.
存储 Bean 分为以下 2 步
首先在java目录下创建一个文件夹用于存放我们的Bean.在文件夹下创建一个User对象.
给User类添加一个方法.这样我们就创建好了用于展示的Bean.
User类代码.
package com.beans;
/**
* name User
* @deprecated exercises:
* 普通类,普通Bean对象
*/
public class User {
public void sayHi(String name) {
System.out.println("Hello: " + name);
}
}
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
beans>
<bean id="user" class="com.beans.User">bean>
获取并使用 Bean 对象, 分为以下 3 步
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;
public class App {
public static void main(String[] args) {
//获取上下文对象,两种方式 都可以用来获取Bean对象
//1.得到Spring上下文对象(参数要和配置文件名称相同)
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
//2.bean工厂
BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("spring.xml"));
//根据上下文对象提供的方法获取到bean 获取有三种方式
//1.根据id获取bean 方法的参数要和xml中的id对应,方法返回Object类型,需要强转.
User user1 = (User) applicationContext.getBean("user");
//使用
user1.sayHi("echo");
//2.根据类型获取bean对象,只适用于Spring容器中只注册了一个此类型对象
//该方式的好处是 不需要强转
//(当Spring中存在多个同一个类型对象不适用)
User user2 = applicationContext.getBean(User.class);
user2.sayHi("echo");
//3.根据类型+id 获取bean对象
//不需要强转,也不会查询到多个,因为注册到Spring容器中对象的id是唯一的.
User user3 = applicationContext.getBean("user", User.class);
user3.sayHi("echo");
//根据beanFactory来获取对象.三种方式同样适用
User user4 = (User) beanFactory.getBean("user");
user4.sayHi("XX");
User user5 = beanFactory.getBean(User.class);
user5.sayHi("XX");
User user6 = beanFactory.getBean("user", User.class);
user6.sayHi("XX");
}
}
相同点: 都可以实现从容器中获取Bean,都提供了getBean方法
不同点:
要使用注解的方式, 我们首先要 配置扫描路径 让Spring启动时扫描 配置(com.beans)包 中的注解.只有被配置的包下的所有类, 添加注解才能被正确的识别并保存到 Spring 中.
在我们之前的配置文件 “spring.xml” 中配置扫描路径(这里配置的 com.beans Spring启动时就会扫描这个包)
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:content="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<content:component-scan base-package="com.beans">
content:component-scan>
beans>
五大注解是在类之前添加的注解, 添加之后可以让这个类注册到Spring容器中.而方法注解则是要在方法前添加的注解, 可以将方法的返回值注册到Spring容器中.要注意的是方法注解一定要配合五大注解来使用.
五大注解的功能是相同的, 都是将类注册到Spring容器中. 既然功能是相同的, 那为什么还要有五大注解? 原因就是可以使程序员通过注解来了解类的作用.
如图,保证这个类所在的包在注册的包范围内.并且在类前添加了五大注解.这个类就被注册到Spring中了
添加到Spring容器中之后, 我们就可以通过之前的方法来获取和使用Bean对象了.
五大注解的命名规则是根据 JDK Introspector 中的 decapitalize 方法 来执行的.(图中代码为源码)
根据源码,我们可以知道命名规则:
如果名称长度大于1, 并且名称中第一个字符和第二个字符都是大写, 就返回原类名.
否则就将类名中的第一个字符从大写转变为小写返回.
知道了五大注解的命名规则. 我们在获取通过五大注解注册的Bean对象时就不会发生不知道名称的问题了.
观察 @Controller / @Service / @Repository / @Configuration 注解的源码就会发现. 这四个注解都是 @Component 注解的子类
类注解是添加到某个类上的, 而方法注解是放到某个方法上的. 但是要注意的是 方法注解是要配合类注解来使用的. 如果只写了方法注解,没有在类上添加注解. Spring在启动的时候是不会扫描到的.(可以理解为方法注解只会缩小扫描范围,不会扩大扫描范围)
同样: 添加好方法注解和类注解之后, 方法的返回值就被添加到Spring容器中. 我们就可以之前的方法来获取对象.
方法注解的命名规则和五大注解的命名规则大有不同.
这样在根据类型查询到多个对象时,就会属性设置的新名称来查询
既然两种注解实现的效果是相同的,那这两个注解有什么不同呢?
Bean的作用域类型有六种,注意后 4 种状态是 Spring MVC 中的值, 普通的 Spring 项目中只有前两种
Spring中可以使用 @Scope注解 来更改Bean的作用域类型( Spring中的Bean默认作用域类型是单例 )
要先设置属性是因为如果先初始化, 初始化的时候就可能需要使用属性.这个时候属性为null, 就会空指针异常.