Spring
一、Spring概述
(ps:内容来自学习笔记及个人理解。)
1、什么是Spring
- Spring又名春天。
- 2020年,Spring框架的雏形,interface21框架面世。
- 2004年3月24日,Spring以interface21为基础重新设计发布了Spring1.0正式版。
- 创始人:Rod Johnson,悉尼大学音乐学博士;
- 理念:使现有的技术更加容易使用。
- Spring以IOC(控制反转)和AOP(面向切面编程)为核心。
- Spring提供了 展现层 Spring MVC、 持久层 Spring JDBC、 业务层 事务管理等众多的企业级应用技术。
- Spring整合了市面上大多数第三方开源框架和类库,慢慢成为了使用最多的企业应用开源框架。
2、Spring的优势
- 方便解耦,简化开发
通过Spring提供的IOC容器,我们可以将对象之间的依赖关系交由Spring进行控制,避免硬编码所造成的过度程序耦合。 - AOP编程的支持
通过Spring提供的AOP功能,进行面向切面编程,许多不容易用传统OOP实现的功能可以通过AOP来实现。 - 声明式事务的支持
在Spring中,我们可以通过声明式方式灵活地进行事务的管理。 - 方便程序的测试
Spring支持Junit,可以通过注解方便的测试Spring程序。
二、IOC
1、IOC理论
- 概念:IOC(控制反转)是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。(指的是对象的控制权由原来开发者在类种自己手动创建控制,反转到由Spring容器创建控制)
- 作用:Spring用来程序解耦的一门技术。
- 底层:用配置文件+工厂+反射来实现。
2、IOC容器工作原理
- 当Spring的IOC容器加载时,会读取配置文件中的诸多bean。
- 根据bean的class的值寻找对应的Class字节码文件。
- 通过反射技术,创建出一个个对象。
- 创建的对象会被存放到内部的一个Map结构中,等待被使用。
- 当我们需要使用具体的对象时就无须自己创建,而是直接从Spring的IOC容器中取。
三、Spring入门案例(Maven)
1、导入坐标
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
</dependencies>
2、创建dao接口和实现类
//接口
public interface UserDao {
public void save();
}
//实现类
public class UserDaoImpl implements UserDao {
public UserDaoImpl() {
System.out.println("对象创建了!");
}
}
3、加入配置文件
<?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">
<!-- id:唯一标识名(整个xml下唯一) class:类的全限定名 -->
<bean id="userService" class="com.hdd.serviceImpl.UserServiceImpl"></bean>
</beans>
4、测试
public class Demo{
public static void main(String[] args) {
// 创建ioc容器管理对象
ApplicationContext context=new ClassPathXmlApplicationContext("application.xml");
// 问ioc容器要对象
UserService userService =(UserService)context.getBean("userService");
userService.save();
}
}
四、Spring相关API(部分)
1、BeanFactory
- BeanFactory是 Spring 的"心脏"。
- BeanFactory是 IOC 容器的核心接口,它定义了IOC的基本功能。
- Spring使用它来配置文档,管理bean的加载,实例化并维护bean之间的依赖关系,负责bean的声明周期。
2、ApplicationContext
- ApplicationContext由BeanFactory派生而来,可以比喻为Spring的躯体。
- ApplicationContext在BeanFactory的基础上添加了很多功能:
- 支持了aop功能和web应用
- MessageSource, 提供国际化的消息访问
- 通过配置来实现BeanFactory中很多编码才能实现的功能
- ApplicationContext的常用实现类
- ClassPathXmlApplicationContext: 从classpath目录读取配置文件
- FileSystemXmlApplicationContext: 从文件系统或者url中读取配置文件
- AnnotationConfigApplicationContext:当我们使用注解配置容器对象时,需要使用此类来创建 spring 容器。它用来读取注解。
3、两者区别:
- beanFactory主要是面向Spring框架的基础设施,也就是供spring自身内部调用,而Applicationcontext 主要面向Spring的使用者。
- BeanFactroy在第一次使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化,而ApplicationContext是在容器启动时,一次性创建并加载了所有的Bean。
4、个人图解
五、spring配置文件(部分)
1、bean标签
- bean标签:指定创建对象的
- id属性:唯一标识(配置文件中唯一)
- class属性:实现类的全限定名
- scope属性:范围,取值:singleton(单例默认) prototype(多例) 扩展:request,session,globesession…
- singleton:对象是随着容器的创建而创建 随着容器的销毁而销毁 自始至终只有一个对象
- prototype:对象的创建和销毁与容器的创建和销毁无关;每次执行getBean的时候创建新的对象;调用一次创建一次;销毁是会等待垃圾回收机制自动完成的
- init-method属性: 对象创建之后指定调用方法
- destroy-method属性:对象销毁后指定调用方法
2、Spring创建对象实例三种方式
(1)构造方式
- 它会根据默认无参构造函数来创建类对象。如果 bean 中没有默认无参构造函数,将会创建失败。
<!--
构造方法实例化
底层使用的是构造器创建对象
-->
<bean id="userService" class="cn.itcast.serviceimpl.UserServiceImpl"></bean>
(2)静态工厂
- 静态工厂:不产生工厂的实例,直接调用工厂的静态方法创建对象。
/**
* 静态工厂
*/
public class Factory {
public static Object getBean(){
return new UserServiceImpl();
}
}
<!--
静态工厂
class="com.hdd.utils.Factory" 工厂全限定类名
factory-method="getBean" 创建userService对象的静态方法
-->
<bean id="userService" class="com.hdd.utils.Factory" factory-method="getBean"></bean></bean>
(3)实例化工厂
- 实例工厂:先产生工厂的实例,再调用工厂实例的方法创建对象。
/**
* 实例工厂
*/
public class Factory2 {
public Object getBean(){
return new UserServiceImpl();
}
}
<!--
实例工厂
先实例化工厂
<bean id="factory" class="com.hdd.utils.Factory2"></bean>
再调用方法创建userService对象
<bean id="userService" factory-bean="factory" factory-method="getBean"></bean>
factory-bean="factory" 告诉spring容器从哪个工厂来创建实例
-->
<bean id="factory" class="com.hdd.utils.Factory2"></bean>
<bean id="userService" factory-bean="factory" factory-method="getBean"></bean>
六、依赖注入
1、概念
- 依赖注入:Dependency Injection。 它是 spring 框架核心 ioc 的具体实现。我们的程序在编写时, 通过控制反转,把对象的创建交给了spring,但是代码中不可能出现没有依赖的情况。比如我们的Book中可能引入一个Publish类,在使用了Spring之后,它会为我们解决这些依赖对象的注入。
2、依赖注入方式
(1)构造方法注入
public class UserServiceImpl implements UserService {
/*
* spring除了提供了ioc容器用来创建管理对象
* 也提供了一个技术可以用来给对象的各种属性赋值:依赖注入(DI)
* 对象的属性:
* 简单属性:string interger double...
* 对象属性:userDao
* 复杂属性: 数组 list set 单列 | map properties 双列
* 依赖注入(di):构造器方式赋值 set属性方式赋值
* */
// 简单属性
private String name;
private Integer age;
// 构造器方式
public UserServiceImpl(String name, Integer age) {
this.name = name;
this.age = age;
}
@Override
public void save() {
System.out.println(name+":"+age);
}
// 对象属性
private UserDao userDao;
// 构造器方式
public UserServiceImpl(UserDao userDao) {
this.userDao = userDao;
}
public void save() {
userDao.save();
}
}
<!-- dao -->
<bean id="userDao" class="com.hdd.daoimpl.UserDaoImpl"></bean>
<!--service -->
<bean id="userService" class="com.hdd.serviceimpl.UserServiceImpl">
<!--构造器的属性赋值
constructor-arg标签
属性:
index:数组角标的方式定位属性
name: 属性名的方式定位属性
type: 属性的全限定名类型定位属性
*****以上三种是用来定位属性的
value: 给简单数据赋值的
ref: 给对象属性进行赋值的(条件:对象值必须也是有ioc容器管理的)
*****以上二种是用来给属性赋值的
-->
<!-- 构造器简单属性赋值方式:-->
<constructor-arg index="0" value="jack"></constructor-arg>
<constructor-arg index="1" value="18"></constructor-arg>-->
<constructor-arg name="name" value="jack"></constructor-arg>
<constructor-arg name="age" value="18"></constructor-arg>
<constructor-arg type="java.lang.String" value="jack"></constructor-arg>
<constructor-arg type="java.lang.Integer" value="18"></constructor-arg>
<!--构造器对象属性赋值
ref:指向的是被spring容器管理bean的id
-->
<constructor-arg name="userDao" ref="userDao"></constructor-arg>
(2)set方法注入
public class UserServiceImpl implements UserService {
/*
* spring除了提供了ioc容器用来创建管理对象
* 也提供了一个技术可以用来给对象的各种属性赋值:依赖注入(DI)
* 对象的属性:
* 简单属性:string interger double...
* 对象属性:userDao
* 复杂属性: 数组 list set 单列 | map properties 双列
* */
/*set方式注入--简单类型*/
private String name;
private Integer age;
public void setName(String name) {
this.name = name;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public void save() {
System.out.println(name+":"+age);
}
/*set方式注入--对象类型*/
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void save() {
userDao.save();
}
/*set方式注入--复杂单列类型*/
private Set<Object> arr;
public void setArr(Set<Object> arr) {
this.arr = arr;
}
@Override
public void save() {
System.out.println(arr);
}
/*set方式注入--复杂双列类型*/
private Properties properties;
public void setProperties(Properties properties) {
this.properties = properties;
}
@Override
public void save() {
System.out.println(properties);
}
/*set方式注入--复杂双列类型*/
private Map<String,Object> map;
public void setMap(Map<String, Object> map) {
this.map = map;
}
@Override
public void save() {
System.out.println(map);
}
}
<!-- dao -->
<bean id="userDao" class="com.hdd.daoimpl.UserDaoImpl"></bean>
<!--service -->
<bean id="userService" class="com.hdd.serviceimpl.UserServiceImpl">
<!--set属性注入方式
property
name属性:按照set后面的值来定位属性的(首字母小写)
value属性:给简单类型赋值
ref属性:给对象属性进行赋值的(条件:对象值必须也是有ioc容器管理的)
-->
<!--简单属性-->
<property name="name" value="jack"></property>
<property name="age" value="18"></property>
<!--对象属性-->
<property name="userDao" ref="userDao"></property>
<!--复杂属性 单列
数组 list set
三组搭配随意用: <array> <list> <set>
-->
<property name="arr">
<set>
<value>abc</value>
<ref bean="userDao"></ref>
</set>
</property>
<!--复杂属性 多列-->
<property name="map">
<map>
<entry key="key1" value="abcd"></entry>
<entry key="key2" value-ref="userDao"></entry>
</map>
</property>
<property name="properties">
<props>
<prop key="username">root</prop>
<prop key="password">root</prop>
</props>
</property>
</bean>