Spring是什么?
翻译:春天
意义:javaEE开发者的春天
是一个一站式的分层结构 轻量级开发框架
目前最受欢迎的框架
特点:
1.开源
2.轻量级(体积小)
3.分层架构(按需添加)
4.一站式(对目前流行的框架支持非常高)
就把它理解为对象的管家,帮我们管理项目中用到的对象,其实说白了就是容器
使用Spring带来的好处
1.降低复杂性
2.松耦合
3.高性能
4.易测试 junit
5.声明式事务
Spring的用法
创建Spring
1.下载需要的jar
https://repo.spring.io/release/org/springframework/spring/
2.导入核心包 beans context expression core logging(日志包)
3.创建编写配置文件
创建对象交给Spring来管理
<!-- 让Spring帮我们管理Person的对象,这个对象的名字叫做person
class 全类名 要被管理的类的名字
name 被管理对象名称
-->
<bean class="com.lanou.Person" name="person">
<property name="name" value="张三"></property>
<property name="age" value="30"></property>
<property name="car" ref="car"></property>
</bean>
4.创建ApplicationContext容器
public static void main(String[] args) {
//想要从容器中获取被管理的对象
//1.创建容器
ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
//2.从容器中获取bean
Person p = (Person) ac.getBean("person");
//查看是否获取成功
System.out.println(p);
思考?在项目中person对象我们没用显示的创建 到底是怎么来的
核心思想
IOC
inverse of control 反转控制
说白的就是把对象的创建反转(交给)给Spring来管理
之前是我们手动new对象,现在是问Spring拿对象
实现原理:通过反射+配置文件来达到
Class c = Class.forName("com.lanou.Person");
Object o = c.newIncetance();
context.put("person",o);
context.get("person");
DI技术
dependency injection
依赖 注入
类A中需要B类提供的功能 称为A依赖B 例如:Service依赖DAO
UserDao dao = new UserDaoimplForJDBC();
UserDao dao = new UserDaoimplForHibernate();
使用Spring之后
UserDao dao = context.getBean("userDaoImpl");
//不需要修改源代码就能实现组件的切换
注入:从外部把需要的对象放到内部就叫注入
UserService
private UserDao dao;
set and get
依赖注入的最终目的就是提高程序的扩展性,尽可能不去修改源代码
依赖注入的三种方式
1.set注入(就是通过set方法,所以必须有set方法)
<bean class="com.lanou.Person" name="person">
<!-- 1.set注入 属性必须提供set方法
value属性用于注入基础数据类型
ref属性用于注入引用类型
-->
<property name="name" value="张三"></property>
<property name="age" value="30"></property>
<property name="car" ref="car"></property>
</bean>
2.构造函数注入
<!-- 2.构造函数注入 调用指定的构造函数并传入参数实现注入 -->
<bean name="person4" class="com.lanou.Person">
<!-- name指定参数名,需要与构造函数一致
index 指定参数放到什么位置 当多个构造函数参数类相同但是顺序不同时
type 指定参数的类型 当多个构造函数的参数顺序相同但是数据类型不同时
-->
<constructor-arg name="car" ref="car" index="0"></constructor-arg>
<constructor-arg name="name" value="120" type="int"></constructor-arg>
<constructor-arg name="age" value="27"></constructor-arg>
</bean>
3.<:p 命名空间
<!-- 3.p命名空间
需要先引入命名空间
xmlns:p="http://www.springframework.org/schema/p"
-->
<bean name="person5" class="com.lanou.Person" p:name="碧瑶" p:age="20" p:car-ref="car"></bean>
4.SPEL
<!-- 4.SpEL注入
SpEL Spring的表达式语言 能够实现一些简单逻辑
与jsp的EL一个性质
-->
<bean name="person6" class="com.lanou.Person">
<!-- 找到一个叫person的对象 调用getName方法获取数据 -->
<property name="name" value="#{person.name}"></property>
<property name="age" value="#{person5.age}"></property>
<property name="car" ref="car"></property>
</bean>
ApplicationContext的两个实现类
ClassPathXmlApplicationContext 用于加载class路径下的配置文件
FileSystemXmlApplicationContext 加载系统路径下的配置文件
public static void main(String[] args) {
//ApplicationContext接口有两个实现类
//从类路径下加载配置文件
ApplicationContext ac1 = new ClassPathXmlApplicationContext("beans.xml");
//从系统路径下加载配置文件
ApplicationContext ac2 = new FileSystemXmlApplicationContext("file:/Users/lanou/java project/java-spring01-4.18/src/beans.xml");
System.out.println(ac1.getBean("person"));
System.out.println(ac2.getBean("person"));
}
bean的创建方式
1.构造函数创建(默认的)
<!-- 2.通过静态方法创建
到PersonFactory中调用getPerson的静态方法来获取对象并放入容器中
如果使用默认的创建方式,Spring会到对应类中找到空参数构造函数
如果指定了factory-method Spring就到类中找到指定的静态方法执行
class指定类型 可以与bean的类型不一致
-->
<bean name="person2" class="com.lanou.PersonFactory" factory-method="getPerson">
<property name="name" value="小红"></property>
</bean>
3.实例工厂创建(调用实例方法获取bean)
<!-- 3.通过实例工厂方法创建
到PersonFactory的某个对象中找getPerson2的方法 获取返回函数,放入容器中
-->
<bean name="person3" class="com.lanou.PersonFactory" factory-method="getPerson2" >
<property name="name" value="晓雪"></property>
</bean>
<bean class="com.lanou.Car" name="car">
<property name="name" value="panamera"></property>
<property name="color" value="red"></property>
</bean>
两种容器
XMLBeanFactory 获取bean时才创建
Application 加载配置时就创建
/*
* Spring提供两种容器 1.BeanFactroy (已过时了) 它是Spring框架最古老的接口 仅定义了实现IOC DI基础功能的接口
* 特点:获取bean时才会创建对应bean 以前的硬件设备资源匮乏 2.ApplicationContext 它的功能更加强大
* 特点:一旦加载配置文件就全部创建了
*
*/
public static void main(String[] args) {
// Resource resource = new FileSystemResource("/Users/yangyuanhu/Documents/Spring/SpringDay01/src/beans.xml");
// XmlBeanFactory
// BeanFactory factory = new XmlBeanFactory(resource);
// System.out.println("配置加载完成");
// System.out.println(factory.getBean("person"));
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
//ac.getBean("person1");
//ac.getBean("person1");
//ac.getBean("person1");
//ac.getBean("person2");
//关闭容器 一般不用
//ac.close();
//获取bean并输出
CollectionBean cBean = (CollectionBean) ac.getBean("cbean");
System.out.println(cBean);
}
bean元素的属性
bean元素的属性
scope
singleton 单例(默认)
prototype 多例
request 与request生命周期一致
session 与session生命周期一致
<bean name="person" class="com.lanou.Person"></bean>
<!-- id与name功能是一样的
id不能重复 不能有特殊字符
name可以重复 可以有特殊字符
scope属性用来指定bean的作用域
singleton:单例 给bean对象在Spring中只存在一个 最常用的 在和Struts2整合时 Action对象不能设置为单例
prototype:多例 每次getBean时都会创建一个新的bean
request 和 session 对象的生存时间与session或request一致
-->
<bean id="person1" scope="singleton" class="com.lanou.Person"></bean>
bean的生命周期方法
<!-- bean的生命周期方法
当我们的对象需要进行一些初始化动作时使用init
销毁时需要释放资源就使用destory-method
注意这两个方法必须是空参无反
-->
<bean id="person2" class="com.lanou.Person" init-method="init" destroy-method="destory"></bean>
//bean创建时
public void init() {
System.out.println("person初始化");
}
//bean销毁时
public void destory() {
System.out.println("person销毁");
}
复杂类型的注入
array 使用array子标签
<!-- 注入数组
当元素只有一个时,直接使用value注入 -->
<property name="array">
<array>
<value>LuLu</value>
<value>LiLi</value>
<value>Job</value>
</array>
</property>
list 使用list子标签 同array
<!-- 注入list集合 也是用value标签-->
<property name="list">
<list>
<value>红</value>
<value>黄</value>
<value>绿</value>
</list>
</property>
map 使用entry子标签
<
property name="map">
<map>
<!-- 使用entry标签来指定键值对 -->
<entry key="name" value="天天"></entry>
<entry key="age" value="12"></entry>
<!-- 如果key或value是一个引用类型 就加上ref -->
<!-- <entry key-ref="abean" value="这是一个bean"></entry> -->
<entry key="有一个bean" value-ref="abean"></entry>
</map>
</property>
properties 使用props子标签
<property name="pop">
<props>
<prop key="jdbcDriver">jdbc:mysql://localhost:3306/MyDB</prop>
<prop key="user">root</prop>
<prop key="password">admin</prop>
</props>
</property>
配置文件的模块化
当一个配置文件内容大多是 可以将其按照功能模块划分
1.在创建容器时 传入多个字符串对象(配置文件名)
2.在配置文件中使用import标签导入
Spring作为框架 当然不应该每次请求都创建一个新的
希望Spring能够跟随项目的启动一并启动,跟随项目的停止一并销毁
实现步骤
1.在web.xml中配置监听器,使得项目启动时spring也能够一起启动
类名org.springframework.web.context.ContextLoaderListener
当监听到应用启动时会创建Spring器并放到ApplicationContext
2.WebApplicationContextUtils 工具用来从WebApplication中取出Spring容器