Spring

1.什么是框架

说明: 将公共的模块(功能) 进行高级的抽取(接口/父级)形成了通用的代码体.
使用: 引入特定的jar包/class/方法 既可以使用框架中的功能.
实际意义: 简化代码的开发.提高软件的扩展性.

2.Spring框架

2.1 Spring介绍

Spring框架是一个开放源代码的,针对bean的生命周期进行管理的轻量级容器(lightweight container)。 Spring解决了开发者在J2EE开发中遇到的许多常见的问题,提供了功能强大的IOC、AOP及Web MVC等功能
Bean: 被spring容器管理的对象称之为Bean

2.2 MVC模型说明

说明: 在大型项目中由于模块众多,如果将所有的项目都写到一起则代码特别的混乱.不便于后期的维护. 所以通过MVC设计模型,将代码进行分级.

实现步骤: 分为3级
1.M(Model) 持久层 代码与数据库进行交互的代码(Mybatis-dao层)
2.C(Control) 控制层 完成某项业务的具体操作过程(Controller层——Service层)
3.V(View) 视图层 一般指用户看到的内容(页面)

MVC模型是大型项目结构设计的设计思想, 目的是为了降低代码的耦合度, 而3层代码结构是设计思想的具体实现方式.

MVC.png

2.3 IOC思想

2.3.1 问题说明

说明: 传统的代码是直接通过new的方式创建对象. 这样的方式将对象与对象紧紧的绑定到一起,不便于代码的扩展.所以需要进行松耦合处理.

2.3.2 IOC说明

控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。
说明: 将对象的创建的权利交给Spring管理,由Spring(第三方)管理对象的生命周期(创建/初始化/使用/销毁).
IOC.png

3 Spring IOC具体实现

3.1 添加jar包文件

3.1.1 spring版本说明

ver.png

3.1.2 引入Spring jar包




org.springframework
spring-core
5.3.6



org.springframework
spring-beans
5.3.6



org.springframework
spring-context
5.3.6



org.springframework
spring-expression
5.3.6



commons-logging
commons-logging
1.2



junit
junit
4.12

4.Spring IOC原理

4.1 Spring容器如何创建对象

1) 当Spring程序执行时,首先会根据配置文件的内容进行解析
2) 当程序解析到bean标签时,则会根据反射的机制实例化对象
3) 将实例化好的对象保存到超大的Map集合中, bean中的Id当做map的Key,实例化好的对象当做Value, 即Map
4) 从容器中获取对象. 则从Map集合中通过id获取对象即可.

4.2 关于反射机制补充说明

反射机制 必然调用对象的无参构造方法
添加有参构造时必须手动添加无参构造

5.工厂模式

5.1 问题

通过spring容器创建的对象一般是通过反射机制调用.但是有的时候由于业务需要, 需要实例化抽象类的对象/复杂的接口对象
说明: Spring提供了工厂模式用于实例化复杂对象

5.2 静态工厂模式

5.2.1 编辑静态工厂

public class StaticFactory{
/通过静态工厂获取数据/
public static Calendar getCalendar(){
return Calendar. getInstance();
}
}

5.2.2 编辑配置文件

<?xml version=”1.0” encoding=”UTF-8”?>
xmlns:xsi="[http://www.w3.org/2001/XMLSchema-instance"](http://www.w3.org/2001/XMLSchema-instance")
xsi:schemaLocation=”http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd”>


5.2.3 编辑测试方法

@Test
public void testStatic(){
ApplicationContext context = new ClassPathXmlApplicationContext(“application.xml”);
Calendar calendar1 = (Calendar) context.getBean(“calendar1”);
System.out.println(“获取当前时间:”+calendar1.getTime());
}

5.3 实例化工厂模式

5.3.1 编辑实例化工厂

public class InstanceFactory{
//获取Calendar对象
public Calendar getCalendar(){
return Calendar.getInstance();
}
}

5.3.2 编辑xml配置文件

<?xml version=”1.0” encoding=”UTF-8”?>
xmlns:xsi="[http://www.w3.org/2001/XMLSchema-instance"](http://www.w3.org/2001/XMLSchema-instance")
xsi:schemaLocation=”http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd”>



## 5.4 Spring工厂模式 说明: 如何需要创建复杂对象 首选工厂模式 ### 5.4.1 编辑工厂代码 public class SpringFactory implements FactoryBean {
//工厂模式实例化对象的方法
@Override
public Calendar getObject() throws Exception {
return Calendar.getInstance();
}
//获取类型
@Override
public Class<?> getObjectType() {
return Calendar.class;
}
//默认条件下spring容器中都是单例对象 节省空间
//对象.方法() 没有安全性问题 提倡使用单例
@Override
public boolean isSingleton() {
return true;
}
} ### 5.4.2 编辑xml配置文件 <?xml version=”1.0” encoding=”UTF-8”?>
xmlns:xsi="[http://www.w3.org/2001/XMLSchema-instance"](http://www.w3.org/2001/XMLSchema-instance")
xsi:schemaLocation=”http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd”>


### 5.4.4 回调执行原理 钩子函数.png # 6.关于单例多例说明 ## 6.1 关于Spring容器对象创建说明 1.Spring容器中默认的对象都是单例对象(通过构造方法实例化对象)
2.有时需要通过多例对象为用户提供服务(数据源链接) ## 6.2 多例对象配置
## 6.3 懒加载 懒加载: 当用户需要获取对象时,容器才创建对象,称之为懒加载
说明: Spring容器中默认的规则是:容器创建则对象创建.
如果需要配置懒加载 则需要添加额外的属性
# 7. Spring生命周期 ## 7.1 生命周期的过程: 1.实例化对象
2.初始化操作 (一般对对象的属性赋值)
3.用户使用对象(调用其中的方法)
4.对象销毁 (一般都是释放资源, 只要容器关闭,则对象销毁) ## 7.2 编辑xml配置文件
## 7.3 编辑测试案例 //测试生命周期运行
@Test
public void testlife(){
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext(“application.xml”);
//获取对象
User user = context.getBean(User.class);
//3.用户调用方法
user.say();
//4.只要容器关闭,则对象销毁
context.close();
} ## 7.4 依赖注入(DI) ### 7.4.1 依赖注入介绍 总结: 对象中的属性, 应该由spring容器动态赋值 ### 7.4.2 关于DI注入说明 两种方式 1.Set注入 2.构造注入









## 7.5 属性注入高级用法 ### 7.5.1 编辑POJO属性 pojo.png ### 7.5.2 编辑xml配置文件





张三
王五
老王




1
2
3










110
米老鼠


## 7.6 抽取集合类型 ### 7.6.1 编辑头标签 <?xml version=”1.0” encoding=”UTF-8”?>
xmlns:util="http://www.springframework.org/schema/util"
xmlns:xsi="[http://www.w3.org/2001/XMLSchema-instance"](http://www.w3.org/2001/XMLSchema-instance")
xsi:schemaLocation=”http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd”>
### 7.6.2 实现对象引用 map.png # 8 Spring容器管理3层代码结构 ## 8.1 代码结构 mvc2.png ## 8.2 关于特殊字符说明 说明: 由于由于业务需要xml配置文件中 可能会有特殊字符,但是该特殊字符与xml关键字(标签)形成冲突.
解决方案: 实现字符串转义 特殊转义字符:
< < 小于号
> > 大于号
& & 和
' ‘ 单引号
" “ 双引号 万能转义字符:
<![CDATA[XXX任意字符]]>
fbb.png # 9.Spring注解模式 ## 9.1 自动装配 ### 9.1.1 说明 Spring基于配置文件 为了让属性(对象的引用)注入更加的简单.则推出了自动装配模式autowire.
1).根据名称自动装配: autowire=”byName”
2).根据类型自动装配: autowire=”byType”




9.2 注解模式

9.2.1 关于注解的说明

Spring为了简化xml配置方式,则研发注解模式.
Spring为了程序更加的严谨,通过不同的注解标识不同的层级 但是注解的功能一样

1).@Controller 用来标识Controller层的代码 相当于将对象交给Spring管理
2).@Service 用来标识Service层代码
3).@Repository 用来标识持久层
4).@Component 万用注解

9.2.2 编辑配置文件

<?xml version=”1.0” encoding=”UTF-8”?>
xmlns:context=”http://www.springframework.org/schema/context
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
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd”>







  1. <!--业务需求2: 不想扫描@controller注解--><br /> **<context:component-scan base-package="com.jt">**<br />** ** <!--通过包扫描 可以加载其他的注解 排除Controller注解--><br />** <context:exclude-filter type="annotation"**<br />** expression="org.springframework.stereotype.Controller"/>**<br />** </context:component-scan>**

9.2.3 属性注解

  • 关于注解的说明
  • 1.@Autowired: 可以根据类型/属性名称进行注入 首先按照类型进行注入如果类型注入失败,则根据属性名称注入
  • 2.@Qualifier: 如果需要按照名称进行注入,则需要额外添加@Qualifier
  • 3.@Resource(type = “xxx.class”,name=”属性名称”)
  • 关于注解补充: 由于@Resource注解 是由java原生提供的,不是Spring官方的.所以不建议使用
    上述的属性的注入在调用时 自动的封装了Set方法,所以Set方法可以省略不写

    9.3 实现MVC结构的纯注解开发

    9.3.1 关于注解说明

    注解作用: 一些复杂的程序 以一种低耦合度的形式进行调用
    元注解:
    @Target({ElementType.TYPE}) 标识注解对谁有效 type:类 method:方法有效
    @Retention(RetentionPolicy.RUNTIME) 运行期有效(大)
    @Documented 该注解注释编译到API文档中.

9.3.2 关于Spring工厂模式说明

1.Spring源码中创建对象都是采用工厂模式 接口:BeanFactory(顶级接口)
2.Spring开发中需要手动的创建对象时,一般采用:FactoryBean(业务接口)

9.3.2.1 (面试题)BeanFactory 和 FactoryBean 的区别?

BeanFactory是Spring的顶级接口,是负责生产和管理bean的一个工厂。在Spring中,BeanFactory提供了IOC容器最基本的形式,给具体的IOC容器的实现提供了规范, 它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。BeanFactory只是个接口,并不是IOC容器的具体实现,但是Spring容器给出了很多种实现

FactoryBean是Spring的业务接口,为IOC容器中Bean的实例化提供了更加灵活的方式,在IOC容器的基础上给Bean的实现加上了一个简单工厂模式和装饰模式. 一般情况下, Spring通过反射机制来创建bean对象, 但在某些情况下, bean对象的创建过程比较复杂(如抽象类), Spring为此提供了一个FactoryBean工厂接口, 用户可以通过实现该接口, 定制实例化Bean的逻辑, 最后通过getBean方法获得的不是FactoryBean实现类对象, 而是实现类中重写的 getObject方法返回的对象.

9.3.3 配置类介绍

说明: 随着软件技术发展,xml配置文件显得臃肿 不便于操作,所以Spring后期提出了配置类的思想.将所有的配置文件中的内容,写到java类中.

9.3.3.1 编辑配置类

@Configuration //标识我是一个配置类 相当于application.xml
@ComponentScan(“com.jt”) //设定包扫描的路径
public class SpringConfig {
}

9.3.3.2 编辑测试代码

//通过配置类测试代码
@Test
public void testAnno(){
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
UserController userController = context.getBean(UserController.class);
userController.addUser();
}

9.3.4 Spring容器管理业务数据@Bean注解

9.3.4.1 @Bean作用

1) 通过该注解,可以将业务数据实例化之后,交给Spring容器管理. 但是@Bean注解应该写到配置类中.
2) 与xml配置文件比较:
1.Spring配置文件写法
2.执行@Bean的方法 将方法名称当做id, 返回值的对象当做value, 直接保存到Map集合中
@Configuration
@ComponentScan(“com.jt”)
public class SpringConfig {
@Bean
public User user(){
User user = new User();
user.setId(101);
user.setUsername(“Spring容器”);
return user;
}
}

9.3.5 Spring动态获取外部数据

9.3.5.1 编辑properties文件 — user.properties

规则: properties文件
# 数据结构类型: k-v结构
# 存储数据类型: 只能保存String类型
# 加载时编码格式: 默认采用ISO-8859-1格式解析 中文必然乱码
# user.name , Spring容器会获取的当前计算机的名称 所以慎用
# 例如: user.name=xxxx
user.id=1001
user.username=鲁班七号

9.3.5.2 编辑配置类

1.@PropertySource
注解用法: @PropertySource(“classpath:/user.properties”)
注解说明: @PropertySource 作用: 加载指定的pro配置文件 将数据保存到Spring容器中

2.@Value
@Value(123) 将123值赋值给Id
@Value(“${user.id}”) 在Spring容器中查找key=user.id的数据.通过 ${} EL表达式语法获取
1619235325(1).jpg

9.4 Spring注解模式执行过程

1).当程序启动Spring容器时 AnnotationConfigApplicationContext 利用beanFactory实例化对象
2).根据配置类中的包扫描开始加载指定的注解(4个). 根据配置文件的顺序依次进行加载
3).当程序实例化Controller时,由于缺少Service对象,所以挂起线程 继续执行后续逻辑.
当构建Service时,由于缺少Dao对象,所以挂起线程 继续执行后续逻辑.
当实例化Dao成功时,保存到Spring所维护的Map集合中. 执行之前挂起的线程.
以此类推 所有对象实现封装.最终容器启动成功
4). 根据指定的注解/注入指定的对象.之后统一交给Spring容器进行管理.最终程序启动成功.

sp.png

9.5 Spring中常见问题

9.5.1 接口多实现类情况说明

原则: Spring中规定 一个接口最好只有一个实现类.
业务需求: 要求给UserService接口提供2个实现类.

解决方法: 可以通过@Qualifier注解来获取指定实现类的属性名.