Spring快速入门
导入Spring的依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.16</version>
</dependency>
</dependencies>
创建接口以及对应的配置文件
- 接口
package com.waves.dao;
public interface Userdao {
// 简单的写一个方法叫做save
public void save();
}
- 实现类
package com.waves.dao.impl;
import com.waves.dao.Userdao;
public class UserImpl implements Userdao {
public void save() {
System.out.println("Impl......");
}
}
创建配置文件,将我们的实现类配置到xml当中
- 新建文件–XML配置文件–Spring配置文件
<?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>
将实现类配置到xml文件中
# id是我们为这个组件取得名字,class是这个类的全限定名,这样这个类就已经被我们注册到容器当中了
<bean id="Userdao" class="com.waves.dao.impl.UserImpl"></bean>
开始实现
- 创建demo类进行测试
public class Userdemo {
public static void main(String[] args) {
// 这个是我们Spring程序的入口函数,参数为我们创建好的那个配置文件xml
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
// 通过getBean方法获取到我们刚刚在容器中创建好的组件
UserImpl userdao = (UserImpl) app.getBean("Userdao");
userdao.save();
}
}
Bean标签的属性
Bean中属性的简单介绍
- id属性:这是bean标签在容器当中的唯一性标识,这个标识不可重复
- class属性:这是bean标签的全限定名,来自根源的路径,例如我这个跟原路径就是com\waves\demo\Userdemo.java
Bean中的scope属性
- singleton:默认值,单实例,在容器中只有这么一个对象,无论调用多少次这个都是调用的这一个对象
- prototype:多利的,每一次从容器中调用的这个属性的内存地址都是不一样的?
singleton和prototype的区别
1.先准备一个单元测试,junit,导入依赖
<!-- 导入测试依赖-junity -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
</dependency>
2.开始测试–默认值singleton
@Test
public void SingletonOrPrototype(){
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
// 通过getBean方法获取到我们刚刚在容器中创建好的组件
UserImpl userdao = (UserImpl) app.getBean("Userdao");
UserImpl userdao1 = (UserImpl) app.getBean("Userdao");
System.out.println(userdao1 == userdao);
System.out.println(userdao + "\n" + userdao1);
// 打印结果,相等,且内存地址相同
/**true
com.waves.dao.impl.UserImpl@32d2fa64
com.waves.dao.impl.UserImpl@32d2fa64*/
}
3.开始测试–多例的prototype,每次的地址都不相同
@Test
public void SingletonOrPrototype(){
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
// 通过getBean方法获取到我们刚刚在容器中创建好的组件
UserImpl userdao = (UserImpl) app.getBean("Userdao");
UserImpl userdao1 = (UserImpl) app.getBean("Userdao");
System.out.println(userdao1 == userdao);
System.out.println(userdao + "\n" + userdao1);
/**
* false
* com.waves.dao.impl.UserImpl@42f93a98
* com.waves.dao.impl.UserImpl@c46bcd4
*/
}
什么是作用域
singleton和prototype
打开断点进行调试
1、如果是singleton的方式,那么会在加载完配置文件的时候自动创建
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
加载完配置文件的的时候,我们的容器就已经创建了这个对象,且只会创建一次,而不是在这俩行代码执行的时候才创建
UserImpl userdao = (UserImpl) app.getBean("Userdao");
UserImpl userdao1 = (UserImpl) app.getBean("Userdao");
2、如果是prototype的方式,在加载配置文件执行完毕之后,我们使用了getBean方法获取这个对象的时候才给我们创建所需要的对象
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
// 通过getBean方法获取到我们刚刚在容器中创建好的组件
UserImpl userdao = (UserImpl) app.getBean("Userdao");
UserImpl userdao1 = (UserImpl) app.getBean("Userdao");
// 三行代码执行完了两个对象才创建出来,并且内存地址不相同
创建了两次,且内存地址不相同
范围配置–图解
生命周期
- init-method:指定类中的初始化方法的名称
- destory-method:指定类中对象销毁方法的名称
- 把这俩属性套进去
<bean id="Userdao" class="com.waves.dao.impl.UserImpl" scope="prototype"
init-method="init"
destroy-method="destory">
</bean>
- 我先在我的那个实现类中创建两个方法,一个代表初始化,另一个代表销毁方法
// 初始化方法
public void init(){
System.out.println("正在初始化....");
}
// 销毁方法
public void destory(){
System.out.println("正在销毁.....");
}
开始调用
需要注意,原先的加载配置文件的方法本质上是接口的调用和实现
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
ApplicationContext他是没有关闭方法的,所以如果我们这个单元测试类结束的话是看不到销毁方法的,越子集功能越强大
我们要把ApplicationContext换成ClassPathXmlApplicationContext
public static void main(String[] args) {
// 这个是我们Spring程序的入口函数,参数为我们创建好的那个配置文件xml
ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
// 通过getBean方法获取到我们刚刚在容器中创建好的组件
UserImpl userdao = (UserImpl) app.getBean("Userdao");
userdao.save();
app.close();
}
Bean实例化的方式
默认无参构造的创建
这个是我们之前的例子里面用的
工厂静态方法实例化
- 先创建一个类,叫做静态工厂
public class StaticFactory {
// 这里设置一个静态方法,返回一个UserDao的对象
public static UserDao getUserDao() {
System.out.println("静态工厂实例化...");
return new UserImpl();
}
}
-
配置好xml文件–他会根据你设置的全限定名中,内部指定的这个方法(getUserDao),去返回对应的对象
-
<bean id="Userdao" class="com.waves.factory.StaticFactory" factory-method="getUserDao"></bean>
-
开始测试
-
public static void main(String[] args) { // 这个是我们Spring程序的入口函数,参数为我们创建好的那个配置文件xml ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml"); // 通过getBean方法获取到我们刚刚在容器中创建好的组件 /*UserImpl userdao = (UserImpl) app.getBean("Userdao"); userdao.save();*/ UserImpl userdao1 = (UserImpl) app.getBean("Userdao1"); app.close(); }
-
-
出现这个是因为我没有把xml配置文件一开始的那个Bean标签删除掉,所以会在配置文件加载完毕的时候马上调用一次最初的Userdao对象,然后才开始加创建我静态工厂的那个Usredao对象
工厂实例方法实例化
- 一样的,先创建我们动态的工厂
// 动态工厂创建
public class DynamicFactory {
// 动态工厂实例化
public UserDao getUserDao(){
System.out.println("动态工厂创建.....");
return new UserImpl();
}
}
-
配置我们的xml文件–重点
-
因为是动态的,我们在调用里面的这个getUserDao方法的时候,必须先有我们的这个工厂对象
-
所以他需要先创建,我们的工厂对象就创建好了
-
<bean id ="factory" class="com.waves.factory.DynamicFactory"></bean>
-
但是我们要的不是这个工厂对象,而是这个工厂对象中的那个getUserdao()得方法,
-
所以我们在创建一次那个Userdao的对象,在容器中。
-
<bean id = "Userdao3" factory-bean="factory" factory-method="getUserDao"></bean>
-
啥意思?我要获得Userdao3这个对象,我需要到这个工厂(factory-bean=“factory”)的方法(factory-method="getUserDao")中去创建对象
-
实战
-
public static void main(String[] args) { // 这个是我们Spring程序的入口函数,参数为我们创建好的那个配置文件xml ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml"); // 通过getBean方法获取到我们刚刚在容器中创建好的组件 /*UserImpl userdao = (UserImpl) app.getBean("Userdao"); userdao.save();*/ UserImpl userdao1 = (UserImpl) app.getBean("Userdao1"); UserImpl userdao2 = (UserImpl) app.getBean("Userdao2"); app.close(); }