目录
2、在 Maven 项目中,添加 Spring 框架支持(spring-context,spring-beans)
1.在 Spring 项目中添加配置文件。【如果不是第一次添加Bean对象可以跳过此步骤】
2.先创建⼀个 Bean对象,并将它注册到 Spring中。
对比:@Resource VS @Autowired 的区别
一、Spring初识
什么是Spring?
Spring 指的是 Spring Framework,它是⼀个开源框架,有着活跃⽽庞⼤的社区。Spring ⽀持⼴泛的应⽤场景,它可以让 Java 企业级的应⽤程序开发起来更简单。
⽤⼀句话概括 Spring:Spring 是包含了众多⼯具⽅法的 IoC 容器。
什么是loC?
IoC( Inversion of Control)是 “控制反转” 的意思, 也就是说 Spring 是⼀个 “控制反转” 的容器。
举个例子,比如我们在 A 类中,想去调用 B 类中的方法。
如果没有 IoC 容器的话,就需要在A类中创建一个 B 对象,这时就需要 new B() 或者使用已经创建出来的 B 对象,但无论是哪种情况,A 对象掌握了绝对的主动权。
如果引入 IoC 容器的话,当 A 类中需要使用 B 对象时,IoC 容器会主动创建出一个 B 对象,注入到 A 的类中。此时对象 A 就变成了被动方,控制权 “反转给了” Spring 框架,也就是 “控制反转”了。我们可以看到,对象的创建和销毁的权利都交给 Spring 来管理了,它本身⼜具备了存储对象和获取对象的能力,这就是 IoC 容器。
注:Spring 会帮我们管理所有的对象,在 Spring 中对象叫做 Bean。我们可以将 Bean 存储到 Spring 容器中,也可以将 Bean 从 Spring 容器中取出来。
二、创建Spring项目
1、创建一个 Maven 项目
点击New Project,选择Maven,然后一路next。
2、在 Maven 项目中,添加 Spring 框架支持(spring-context,spring-beans)
在项⽬的 pom.xml 文件中,添加 Spring 框架的⽀持,xml 配置如下:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
</dependencies>
添加的框架有 spring-context:spring 上下文,还有 spring-beans:管理对象的模块。
3、创建一个启动类 和 main 方法
在 src.main.java目录下,创建一个 Java类,并写一个main方法。如果能够正常运行说明项目成功创建。
三、将 Bean 对象存储到容器(Spring)中
1.在 Spring 项目中添加配置文件。【如果不是第一次添加Bean对象可以跳过此步骤】
在resources文件夹下New一个File文件,命名为sping_config.xml,然后将以下代码拷贝至sping_config.xml中。
<?xml version="1.0" encoding="UTF-8"?>
<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>
2.先创建⼀个 Bean对象,并将它注册到 Spring中。
我们可以设置一个目录专门存放 Bean 对象。
然后为它写一个方法,可以如下所示:
public class User {
public void sayHi(String name){
System.out.println("你好"+name);
}
}
此时我们需要将这个 Bean 对象存入 spring, 后面再从spring中读取到 User,然后调用里面的方法。
我们需要对 spring_config.xml 配置文件,进行如下操作。
<bean id="user" class="com.beans.User">
</bean>
简单来说,我们要将Bean对象存入Spring,是通过键值对的形式存储的(有点类似map)——key就是id,也就是Bean对象的别名(id 的值可以与类名不相同,可以任意起,只要自己记得);value是类本身所在的具体位置,注意要把类所在的详细路径写下来。然后我们在获取Bean对象时,就是通过 id 别名来找到对应的 Bean 对象。
3.获取并使用 Bean 对象。
分为以下三步:
1、获取 Spring 上下文对象。
在启动类main方法中,通过ApplicationContext类获取Spring上下文。这个类源自我们刚才引入的spring-context框架。
new的对象 ClassPathXmlApplicationContext("spring_config.xml") 是描述Bean对象所在的xml文件(刚刚我们才将其配置,注意不要写错)。获取上下文对象,其实就是获取配置文件里的全部对象。
2、再通过上下文对象提供的方法,获取我们自己需要使用的 bean 对象。
要获取我们需要使用的 bean 对象,只需要调用getBean方法,根据 id 取出相应的 bean 对象,强转成对象对应的类型。
3、拿到 bean 对象之后,就可以使用 bean 对象了。
演示代码如下:
//1.先得到spring上下文对象,ApplicationContext 或者 BeanFactory
ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");
//ApplicationContext加载全部bean; BeanFactory按需加载
//2.根据上下文对象提供的方法获取到bean
User user=(User)context.getBean("user");//必须和spring里的id保持一致
//3.可以使用了
user.sayHi("张三");
以上,如果能正常打印,就说明我们通过 Spring ,成功地将对象进行了存储和读取操作。
ps. 当然,getBean有其他的重载方法,比如通过类名来获取,如下所示:
User user=context.getBean(User.class);
除了 ApplicationContext 之外,我们还可以使⽤ BeanFactory 来作为 Spring 的上下文。使用起来也是差不多的,不再赘述。我们接下来看更重要的,通过注解来实现更方便的存储和读取对象。
四、Spring 注解实现更简单的读取和存储对象
前置工作:配置扫描路径
因为我们不是采用手动的注入的方式了,而是使用自动扫描的方式。所以想要将对象成功的存储到 Spring 中,我们需要配置⼀下存储对象的扫描包路径,被配置的包路径下的所有添加了注解的类都会被自动识别并保存到 Spring 中。
步骤:在spring_config.xml里面应该加入以下代码:
<?xml version="1.0" encoding="UTF-8"?>
<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=""></content:component-scan>
</beans>
这个base-package里面的内容需要我们自己添加,就是存放bean对象的根目录。
我们扫描的时候只扫描 base-package 里面的类 ,不在里面的类即使加入了注解也不会被扫
描。
效果如图所示:
思考:为什么要只加载特定目录里面的类呢?
因为不是所有的类都要把它放到Spring容器里面。有些普通的类对象并不会被别人使用,不需要注册到 Spring 里。所以我们只加载特定的要放入的类。
一、通过注解存储 Bean 对象
注:Spring 中的注解是通用的,在 Spring Boot 和 Spring MVC 中,也能够使用 Spring 的注解。
1、类注解
1、@Controller 【Controller - 控制】
2、@Service 【service - 服务/业务】
3、@Repository 【repository - 仓库】
4、@Configuration 【configuration - 配置】
5、@Component 【component - 组件】
通过上述五大类注解中的任何一个,都可以将 bean 存储到 Spring 中。
举个例子:
我们只需要添加一个注解(五大类注解中任意一个都行),就可以将 bean 存入 Spring 中。现在我们还没讲到通过注解获取对象,所以仍然使用 ApplicationContext。我们看到能够正常输出打印,说明对象被正确地输入了。
注:要存入 Spring 中的 bean,必须处于配置文件的根目录下,而且注解不可省略!
同理,将 @Controller 改成 @Service、@Repository、@Configuration、@Component,都是可以成功执行的。
思考:五大类注解有何区别?
在开发中为了描述每一个类所属的功能,让人直接了解当前类的用途,我们就引入了五大类注解来帮助区分。
@Configuration 配置类,一些负责配置信息的类,放在配置层。
@Controller 控制类,主要是验证前端发过来的参数,放在业务逻辑层。
@Service 服务类,数据的处理和接口的调用(Dao层的接口),放在服务层。
@Repository 仓库类,主要是对数据库的操作,也叫做Dao类,放在持久层。
@Component 组件类,一些外部实现的工具类。
2、方法注解
@Bean ,也可以将一个 bean 存储到 Spring 中。
类注解是添加到某个类上的,而方法注解是放到某个⽅法上的,也就是说这个方法的返回值是一个对象。
例子:
我们先创建一个User类,用于待会函数返回对象用。
然后创建一个UserBean类,写一个返回User对象的方法并加上@Bean注解。
此时运行一下发现找不到这个对象。
这是因为@Bean 必须搭配五大类注解才能使用。我们需要在类前面加一个类注解,如下所示:
此时再运行就能成功获取该对象。
注意:
1、@Bean写在方法的前面,五大类注解放在类的前面。
2.、@Bean 必须搭配五大类注解才能使用。
二、通过注解获取 Bean 对象
两种注入关键字:
@Autowired
@Resource
两种关键字均可使用。我们先看使用,下面再来介绍它们的区别。
1.属性注入
1.1演示使用 @Autowired 实现属性注入
先创建一个UserService类,实现一个方法
然后将他注入到UserController的属性中
执行main函数获取UserController的对象,然后调用其方法,看是否能成功调用UserService对象的方法。如果成功,说明UserService对象成功注入到了UserController的属性中。
1.2演示使用 @Resource 实现属性注入。
可以成功执行
2.构造方法注入
我们新建一个 UserController2 类,它有一个UserService对象。现在我们想通过构造方法+注解的方式注入对象,只要在构造方法前加上@Autowired。
看下执行效果,能正常打印 ,说明注入成功。
对比传统构造方法和构造方法注入的区别:
以前写法,耦合度高,当UserService构造方法改变时,UserController构造方法要跟着变。
userService= new UserService();
构造注入写法,解耦合,直接获取UserService的对象来用,不依赖UserService构造方法。
this.userService=userService;
注:@Resource 注解不支持构造方法注入。
这里直接报错了
3.setter注入
我们创建一个 UserController3 类,它有一个UserService对象。现在我们想通过set方法+注解的方式注入对象,只要在set方法前加上@Autowired。
能够正常输出,说明setter注入成功。
另外,@Resource也支持 Setter 注入。如下所示:
对比:@Resource VS @Autowired 的区别
1、出身不同:
Autowired属于Spring框架
Resource属于Jdk
2、使用范围不同:
Autowired可以作用于构造方法注入、属性注入、setter注入
Resource可以作用于属性注入、setter注入
3、参数个数不同
Autowired只有一个参数:required
Resource有多个参数:name,、lookup、type,…
对比:三种注入方式的区别
- 属性注入使用方便。但是缺点是只能适用于IoC容器,在非IoC容器不适用。
- 构造方法注入是最推荐的注入方式。 缺点是如果注入多个对象,就会包含多个参数。优点通用性强,在使用前一定可以保证属性构造好了。
- Setter方式注入是Spring前期推荐的注入方式,针对一个参数进行构造,通用性不如构造方法注入。
4.一个Bean对象被注入多次怎么处理
如果一个Bean的对象被注入了多次,那么获取对象的时候怎么区分到底是哪一个对象呢?
例如UserBean类有两个对象注册到了Spring里,此时注入
此时直接注入会报如下的错误,提示找到了两个对象。
解决办法:
1.注入时直接写Bean对象的名字
直接清楚的描述类的名字。
使用@Resource和@Autowired属性注入的方式,但被注入属性对象名要和注入对象的名字一样
首先为这两个对象取个不同的名字,以便注入区分。
扩展——@Bean重命名:
当@Bean 没有设置 name 属性时,那么 beanName 默认就是方法名。
但是这样的话,注入对象时就要通过方法名来获取bean对象,很不方便(获取的是 bean,却填一个方法名)。所以可以通过设置@Bean的name属性来对方法重命名,写法如下:@Bean(name="xxx"),或者@Bean(name={"xxx1", "xxx2"})。当设置 name 属性之后, name 属性对应的值,就是 beanName,而且属性的值可以有多个。但是此时方法名就不可以使用了。
此时注入user1,只需要将属性名改成一样的名字,就可以获得user1的信息
注入user2,即可获得user2的信息
2.使用@Resource的name属性
如果觉得属性名必须要和注入对象名完全一致很麻烦,那么可以在@Resource的name属性中设置对象的名字(name="xxx"),写什么名字就注入什么名字的对象。
这样属性名既可以随便取,也能获取对应的Bean对象。
3.使用@Autowired+@Qualifier
这种方法和@Resource异曲同工。因为Autowired没有name属性,所以我们采用Qualifier来帮助我们。@Qualifier 注解相当于一个筛选器,对 @Autowired注解查询的结果进行筛选。
总结
本文介绍了Spring的基本使用,接下来去我会介绍 Spring Boot 的使用方法。