spring概述
Spring框架轻量级一站式框架。 提供了两个核心 IOC , AOP 。
轻量:
一站式: spring在三层架构都提供了相应的解决方案。
Dao: JdbcTemplate模板对象,简化jdbc开发。 (DbUtils框架)
Service: 提供了声明式事务的管理操作。
Web: springmvc 框架:
spring框架的优点
Spring框架的出现, 使得javaEE开发更加简单。
面向接口开发, 不是针对类。 更加利于扩展和维护。
能够使得程序耦合度降低(松耦合)
Spring能够整合外部优秀的框架。
Spring当中整合了单元测试, 测试更加方便。
Spring当中提供了声明式事务。 配置就可以解决事务~
…
任何javaEE程序都可以从spring当中受益 。
spring框架的组成
架的基本组成。 spring框架运行, 必须依赖core。
Aop 模块相关: 面向切面编程~
Web: 在web层提供了相应的技术: springmvc servlet
Data access: jdbc ORM:(整合外部的优秀框架, Mybatis,Hibernate) Transactions
Test: 整合了junit单元测试:
spring核心IOC
IOC概述
控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。
创建对象的权利翻转交给spring框架完成。 对象放在一个IOC容器当中, 需要使用的时候从容器当中获得一个就OK。 该过程就是一个控制翻转的过程。
传统:
Dao: service: web: 层层之间依赖关系(UserService层当中出现了Dao代码): 不利于扩展, 不利于维护。
Service:
Public class UserService{
UserDao dao = new UserDaoImpl();
}
Spring: ioc 就可以解决上述问题。 耦合度高的问题。
我们需要使用对象的时候, 不用直接new 关键字创建。从容器当中获得一个对象。
IOC入门案例
搭建spring环境。
(1)创建工程: maven jar
(2)引入spring的相关依赖:
(3)引入spring核心配置文件: 名称可以任意: applicationContext.xml spring_xxx.xml
(4)IOC: 配置
(5)测试
创建maven jar工程
springDemo
引入spring的依赖
引入spring的核心配置文件applicationContext.xml
从官网copy: xml的头信息~
spring官网:https://spring.io/
Spring的文档地址::https://docs.spring.io/spring-framework/docs/5.2.10.RELEASE/spring-framework-reference/core.html#spring-core
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!--管理bean-->
<bean id="car" class="com.offcn.pojo.Car"/>
</beans>
测试
@Test
public void shouldAnswerWithTrue()
{
//读取配置文件: 创建了IOC容器:容器当中保存了配置文件当中配置的bean对象:
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
//从容器当中根据id获取对象:
Car car = (Car) context.getBean("car");
System.out.println(car);
// 容器关闭:
context.close();
}
IOC容器对象的方法补充
@Test
public void test1()
{
//读取配置文件: 创建了IOC容器:容器当中保存了配置文件当中配置的bean对象:
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
//从容器当中根据id获取对象:
Person person = (Person) context.getBean("person");
System.out.println(person);
//根据类型从容器当中查询:
Person bean = context.getBean(Person.class);
System.out.println(bean);
System.out.println("xxxxx");
String[] names = context.getBeanDefinitionNames();
System.out.println(Arrays.toString(names));// [car, person]
//Map<id,Person>
Map<String, Person> beansOfType = context.getBeansOfType(Person.class);
System.out.println(beansOfType);
// 容器关闭:
context.close();
}
DI 依赖注入
setter注入:
<!--管理bean-->
<bean id="car" class="com.offcn.pojo.Car">
<!--setter注入:-->
<property name="name" value="兰博基尼"/>
<property name="color" value="蓝色"/>
<property name="price" value="3000000"/>
</bean>
<!--bean配置person-->
<bean id="person" class="com.offcn.pojo.Person" >
<!--
setter注入:
(1)实体类当中必须存在setter方法:
(2)注入的是一个普通属性: value值:
(3)注入的是一个对象属性: ref
-->
<property name="username" value="鹏程"/>
<property name="age" value="30"/>
<property name="car" ref="car"/>
</bean>
构造器注入
<!--管理bean-->
<bean id="car" class="com.offcn.pojo.Car">
<!--构造器注入:提供对应的构造器: -->
<constructor-arg name="name" value="迈巴赫"/>
<constructor-arg name="color" value="黑色"/>
<constructor-arg name="price" value="1200000"/>
</bean>
<!--bean配置person-->
<bean id="person" class="com.offcn.pojo.Person" >
<!--构造器注入: -->
<constructor-arg name="username" value="王磊"/>
<constructor-arg name="age" value="30"/>
<constructor-arg name="car" ref="car"/>
</bean>
总结: setter注入, 构造器注入就是常用的注入方式。
名称空间注入
P名空间在spring2.0 引入: 我们使用的版本肯定支持。
步骤一: 引入p名称空间 xmlns:p=“http://www.springframework.org/schema/p”
步骤二: 使用P名称空间:
P:属性名称= value;
<!--管理bean-->
<bean id="car" class="com.offcn.pojo.Car"
p:name="大奔" p:color="黑色" p:price="1000000">
</bean>
<!--bean配置person-->
<bean id="person" class="com.offcn.pojo.Person" p:username="杨文斌" p:age="20" p:car-ref="car" >
</bean>
SPEL注入:
SpEl 注入使用了spring 框架提供的spring el表达式进行注入。 功能最强大。
Value的值可以是简单类型的值: 可以是方法调用之后获得值。 可以是从配置文件当中获得值。
Spring3.0 版本提供的新特性。
<!--管理bean-->
<bean id="car" class="com.offcn.pojo.Car">
<!--SpEl注入: 功能最强大 : springEL
#{}
#{''}
#{数值元素}
#{方法调用}
如果注入的是一个对象类型, 属性依然使用value属性
-->
<property name="name" value="#{'wangzong'}"/>
<property name="color" value="#{car.getColor()}"/>
<property name="price" value="#{3000000+1}"/>
</bean>
<!--bean配置person-->
<bean id="person" class="com.offcn.pojo.Person" >
<property name="username" value="#{'mrzhang'}"/>
<property name="age" value="18"/>
<!--引入的一个对象类型, 依然使用value属性: -->
<property name="car" value="#{car}"/>
</bean>
DI注入集合类型
注入数组类型
<bean id="user" class="com.offcn.pojo.User">
<property name="id" value="1001"/>
<property name="name" value="张万伟"/>
<property name="names" >
<array>
<value>张三丰</value>
<value>老张</value>
<value>张同志</value>
<value>狗蛋</value>
</array>
</property>
</bean>
注入List集合类型:
<!--注入list集合: -->
<property name="hobbies" >
<list>
<value> 学习java </value>
<value> 学习Mybatis </value>
<value> 学习spring </value>
</list>
</property>
注入set集合类型
<property name="address">
<set>
<value>深圳 </value>
<value>北京</value>
<value>上海</value>
</set>
</property>
注入Map集合类型
<!--map集合:-->
<property name="car" >
<map>
<entry key="car1" value-ref="car"></entry>
<entry key="car2" value-ref="car2"></entry>
</map>
</property>
Properties集合类型
Properties集合: 是一个特殊的map集合: 集合的key 和value都是String类型。 所以不需要指定key 和value。
属性表集合: 因为一般该集合结合外部的xxx.properties文件使用。
xxx.properties文件: 制定key 和value: jdbc.username=root
<!--注入properties集合对象: -->
<property name="prop">
<props>
<prop key="names1">女对象1</prop>
<prop key="names2">女对象2</prop>
<prop key="names3">女对象3</prop>
</props>
</property>
说明:
List集合的底层数据结构: HashMap HashSet
bean实例化方式-三种方式
调用了无参数构造器
默认调用无参数构造器, 对象进行创建。
前提: bean必须提供无参数构造器。
/ new Book();
// 反射: 全限定类型
public Book(){
System.out.println("无参数构造器被执行了.....");
}
静态工厂
静态工厂, 工厂当中提供的方法都是静态方法。 这样的工厂静态工厂。
创建静态工厂的实体类:
public class StaticFactory {
/**
* 静态方法: 随着类的加载而加载。
*
* @return Object对象:
*/
public static Book getInstance(){
System.out.println("static faactory static Method.....");
return new Book();
}
}
配置
<!--静态工厂方式: 生产对象
核心配置文件被读取的时候, 静态工厂当中的静态方法被执行了。
静态方法的返回值存放在IOC容器当中。
class: 指定的静态工厂实例类:
factory-method:静态工厂的静态方法:
-->
<bean id="book2" class="com.offcn.pojo.StaticFactory" factory-method="getInstance"/>
实例工厂
创建工厂类
public class InstanceFactory {
/**
* 创建了一个实例方法:
* @return
*/
public Book getInstance(){
System.out.println("instance factory method execute....");
return new Book();
}
}
配置
<!--将实例工厂交给spring管理
实例工厂:
(1)创建实例工厂:
(2)实例工厂创建对象:
factory-bean:指定工厂类
factory-method:指定工厂类的工厂方法。
-->
<bean id="factory" class="com.offcn.pojo.InstanceFactory"/>
<bean id="book3" factory-bean="factory" factory-method="getInstance"></bean>
bean对象初始化相关
生命周期相关的两个方法
创建了实体类当中相关方法
@Data
public class Book implements Serializable {
private String name;
private double price;
private String auth;
// new Book();
// 反射: 全限定类型
public Book() {
System.out.println("无参数构造器被执行了.....");
}
public void init() {
//方法能够对创建出来的对象进行一个初始化 : 对象----》初始化。
System.out.println("book 对象初始化操作。。。。。。。");
}
public void destroy(){
System.out.println("book 对象销毁之前调用......");
}
}
配置
<!--spring管理book对象:
init-method="init" 指定了对象的初始化方法。 在对象创建之后执行init方法。
destroy-method="destroy" 指定了对象的销毁方法。 在对象销毁之前调用。
只有当工厂关闭的时候,destroy 方法才会被调用。
-->
<bean id="book" class="com.offcn.pojo.Book" init-method="init" destroy-method="destroy" >
<property name="price" value="29.9"/>
<property name="name" value="疯狂java"/>
<property name="auth" value="李刚"/>
</bean>
bean 作用范围
作用域 描述
singleton 在spring IoC容器仅存在一个Bean实例,Bean以单例方式存在,bean作用域范围的默认值。
prototype 每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时,相当于执行newXxxBean()。
request 每次HTTP请求都会创建一个新的Bean,该作用域仅适用于web的Spring WebApplicationContext环境。
session 同一个HTTP Session共享一个Bean,不同Session使用不同的Bean。该作用域仅适用于web的Spring WebApplicationContext环境。
spring容器在创建对象的时机
当IOC容器创建,(工厂)时候, 指定了applicationContext.xml核心配置文件。 配置文件当中配置的bean 都会被创建存放在IOC容器当中。 spring IOC容器默认是单例形式创建对象。
多例模式创建对象
<!--spring管理book对象:
init-method="init" 指定了对象的初始化方法。 在对象创建之后执行init方法。
destroy-method="destroy" 指定了对象的销毁方法。 在对象销毁之前调用。
只有当工厂关闭的时候,destroy 方法才会被调用。
scope="singleton" : 默认值: 单例形式创建对象。
prototype: 多例的模式创建。 spring 整合Struts2 的时候, 多例~
-->
<bean id="book" class="com.offcn.pojo.Book" init-method="init"
destroy-method="destroy" scope="prototype" >
<property name="price" value="29.9"/>
<property name="name" value="疯狂java"/>
<property name="auth" value="李刚"/>
</bean>
如果指定了scope属性为 prototype, 对象多例模式创建。
创建时机: 当从容器当中获得对象的时候, bean对象才会被创建。
创建: 多例模式创建。 每调用一次就会创建一个新的对象。
销毁: 工厂关闭的时候, destroy方法不会调用。 destroy方法只针对单例模式。
总结:实际开发当中一般情况都使用默认单例模式。 spring整合Struts2
的时候使用多例。
scope 属性(面试题目)
默认值: singleton 单例模式创建。
Prototype: 多例模式创建。
Request: 依赖web环境。 创建出来的对象会存在Request当中一份。
Session: 依赖web环境。 创建的对象会存放在session域当中一份。
globalSession: 应用在分布式集群环境当中。 创建的对象存在全局的session当中。
对象的详解
工厂的继承体系图
常用工厂对象的详解
BeanFactory对象:接口类型, 工厂对象, 是一个顶层对象。 一般不直接使用, 留给Spring框架设计者使用。
ApplicationContext 接口: BeanFactory子接口。 该接口提供了更加丰富的功能。 程序员一般使用该接口:
FileSystemXmlApplicationContext: 类, 父接口ApplicationContext 。能够读取文件系统当中的配置文件。
ClassPathXmlApplicationContext : 能够读取类路径下的资源。 类路径~(classes)
BeanFactory和ApplicationContext 区别(面试题目)
BeanFactory主要是面向Spring框架的基础设施,也就是供spring自身内部调用, 而Applicationcontext 主要面向Spring的使用者。
BeanFactroy在第一次使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化, 而ApplicationContext是在容器启动时,一次性创建并加载了所有的Bean。