IoC控制反转和依赖注入
⚫ Spring技术是JavaEE开发必备技能,企业开发技术选型命中率>90% ⚫ 专业角度 ◼ 简化开发,降低企业级开发的复杂性 ◼ 框架整合,高效整合其他技术,提高企业级应用开发与运行效率
一、Spring介绍
Spring是一款非常优秀的基于Java编写的开源的轻量级的用于简化企业级应用开发的应用开发框架,准确的来说Spring其实是一个大家族,其中包含非常多非常优秀的框架,如现在比较流行的SpringBoot以及SpringCloud都属于Spring家族。而我们所说的Spring其实指的是Spring Framework,是Spring家族中最核心的技术,也是其他技术的基础。其中包含有IOC/DI和AOP。
DATA ACCESS:数据访问
WEB
DATA ACCESS/INTEGRATION
DATA INTEGRATION:数据集成
ORM
JDBC
WEBSOCKET
SERVLET
OXM
JMS
WEB:WEB开发
WEB
PORTLET
TRANSACTIONS
面向切面编程
3
AOP:
MESSAGING
INSTRUMENTATION
ASPECTS
AOP
ASPECTS:AOP思想实现
CORE CONTAINER
CORE CONTAINER:核心容器
CONTEXT
BEANS
SPEL
CORE
TEST:单元测试与集成测试
TEST
Spring官网
简化开发、框架整合
1初始Spring
Spring全家桶:
●Spring FrameWork、SpringBoot、SpringCloud——主要学习内容
2Spring系统框架
核心容器——>Aop面向切面编程——>Date&web&单元测试
-O
第一部分:核心容器
第四部分:事务
核心概念(IOC/DI)
IIILL
事务实用开发
容器基本操作
第三部分:AOP
核心概念
第五部分:家族
AOP基础操作
SPRINGMVC
AOP实用开发
SPRINGBOOT
第二部分:整合
SPRINGCLOUD
整合数据层技术MYBATIS
3核心概念
IoC:不需要要自己new对象,由外部(容器)提供对象。在容器中的每一个类标识为Bean。
DI:依赖注入,bean与bean之间依赖关系,比如实现,继承。(给成员变量赋值)
⚫ IoC(Inversion of Control)控制反转 使用对象时,由主动new产生对象转换为由外部提供对象,此过程中对象创建控制权由程序转移到外部,此思想称为控制反转 ⚫ Spring技术对IoC思想进行了实现 Spring提供了一个容器,称为IoC容器,用来充当IoC思想中的“外部” IoC容器负责对象的创建、初始化等一系列工作,被创建或被管理的对象在IoC容器中统称为Bean ⚫ DI(Dependency Injection)依赖注入 在容器中建立bean与bean之间的依赖关系的整个过程,称为依赖注入
数据层实现
业务层实现
PUBLIC CLASS BOOKSERVICEIMPL IMPLEMENTS BOOKSERVICE {
IMPLEMENTS BOOKDAO
PUBLIC CLASS BOOKDAOIMPL
PUBLIC VOID SAVE() {
SYSTEM.OUT.PRINTLN("BOOK DAO SAVE ...");
PRIVATE BOOKDAO BOOKDAO
NEW BOCK:D-OIMPL();
'BOOK
PUBLIC VOID SAVE() {
不用在内部实现
BOOKDAO.SAVE();
依赖DAO对象运行
IOC容器
DAO
SERVICE
在容器内绑定
依赖
通过bean标签:绑定了BookService的实现类型;并且利用<property>对它的成员属性 bookDao进行注入赋值:成功解耦。
55-"COM.ITHEIMA.SERVICE.IMPL.BOOKSERVICEIMPL" ID:"BOOKSERVICE"
<BEAN CLASS
LOC把对象的创建交给容器
NAME:"B1,B2"
"PROTOTYPE" INIT-METHOD:"INIT" DES
IT" DESTROY-METHOD:"DESTROY">
SCOPE
依赖注入:对BOOKSERVICELMPL
"BOOKDAO"
REF-"BOOKDAO"
<PROPERTY
NAME
里面的成员变量赋值
</BEAN>
<BEAN
CLASS-"COM.ITHEIMA.DAO.IMPL.BOOKDAOIMPL" ID-"BOOKDAO"></BEAN>
⚫ 目标: 充分解耦 使用IoC容器管理bean(IoC) 在IoC容器内将有依赖关系的bean进行关系绑定(DI) ⚫ 最终效果 使用对象时不仅可以直接从IoC容器中获取,还可以不用赋值 获取到的bean已经绑定了所有的依赖关系
二、入门案例
1IoC入门版本(XML)
IoC容器是一个Map集合可以通过id来找值。
bean定义id属性在同一个上下文中不能重复
a导入Spring、Junit依赖
b定义相关类,接口、实现类。
c创建配置文件在resource目录下,保证规范命名:applicationContext
JSP TAG LIBRARY DESCRIPTOR
XML CONFIGURATION FILE
SPRING COLNFIG
IGNORE FILE
<bean>
- class类全名:类全名
- id标识:唯一标识
d测试类:
ClassPathXmlApplicationContext(“String config”)
创建容器——>创建对象——>调用方法——>关闭容器
三云三
APPLICATIONCONTEXT.XML
PROJECT
<?XML VERSION"1.0" ENCODING:"UTF-8"?>>
SPRING-01-IOCDIDACODEVLDEAPROJECTSVAL 1
ISRC
KBEANS XMLNS三"HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/BEANS"
2
MAIN
3
XMLNS:XSI:"HTTP://WWW.W3.ORG/2001/XMLSCHEMA-INSTANCE"
JAVA
XSI:SCHEMALOCATION:"HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/BEANS HTTP://WWW.SPRING
4
BL COM.ITHEIMA
DLL DAO
5
Y B IMPL
6
----
BOOKDAOLMPL
7
IOC容器是一个MAP集合
BOOKDAO
8
BEAN标签:配置类的信息,会在10C容器中创建对象
ODOD
LSERVICE
9
CLASS属性:类全名(包名,类名)
ALIMPL
10
ID属性:唯一标识,取个名字,将米通过ID的值来获取对象
C BOOKSERVICELMPL
11
2.配置BEAN
1 B
BOOKSERVICE
1.创建SPRING配置文件
DI UTIL
<BEAN CLASS"COM.ITHEIMA.SERVICE.IMPL.BOOKSERVICEIMPL" ID三"BOOKSERVICE">/BEAN>
</BEANS>
13
APPLICATIONCONTEXT.XML
ITEST
JAVA
COM.ITHEIMA.TEST
TARGET
M POM.XML
三云众
BOOKTEST,JAVE
PROJECT
PACKAGE COM.ITHEIMA.TEST;
SPRING-01-IOC-DI D://CODEVDEAPROJECTSVAVAL
2
SRO
3
IMPORT COM.ITHEIMA.SERVICE.BOOKSERVICE;
MAIN
JAVA
IMPORT ORG.JUNIT.TEST;
4
BIL COM.ITHEIMA
IMPORT ORG.SPRINGFRAMEWORK.CONTEXT.SUPPORT.CLASSPATHXNLAPPLICATIONCONTEXT;
5
DAO
9
3.测试
B IMPL
PUBLIC CLASS BOOKTEST
BOOKDAOLMPL
1/1.IOC入门 通过ID获取IOC容器中的对象
8
BOOKDAO
ATEST
POJO
PUBLIC VOID TESTGETBEANBYID() {
DI SERVICE
10
B IMPL
1.根据 APPLICATIONCONTEXT.XML 去创建一个IOC容器
11
BOOKSERVICELMPL
CLASSPATHXATAPPLICATIONCONTEXT CONTEXT ; NEW CLASSPATIXMLAPPLICATIONTEXTEXT CONFIGLOCATIONCOTIONTERT
12
BOOKSERVICE
13
BUTIL
112.从IOC容器中获取对象(BEAN)
14
RESOURCES
BOOKSERVICE BOOKSERVICE (BOOKSERVICE) CONTEXT .GETBEAN( 1
(NAME:"BOOKSERVICE");
15
APPLICATIONCONTEXT.XM
16
1/3.调用对象的方法
17
COM.ITHEIMA.TEST
BOOKSERVICE.SAVE();
18
BOOKTEST
19
TARGET
1/4.关闭容器
20
MPOM.XML
21
CONTEXT.CLOSE();
SPRING-01-IOC-DI.IML
11 22
STUDY DAY14 D:/CODE\LDEAPROJECTS\AVAUPTL
2DI入门案例
a创建注入对象(一个类中要调用的引用对象):<Bean> 实现类中的私有属性要创建set方法。必须要有setting方法!
PRIVATE BOOKDAO BOOKDAO;
PUBLIC VOID
(BOOKDAO BOOKDAO)
SETBOOKDAO
THIS.BOOKDAO
BOOKDAO;
私有,创建SET方法
即:BookServiceImpl实现类中需要调用BookDao属性,
b依赖注入
- Property:成员变量名,需要保持一致。
<property name="bookDao" ref="bookDao"/>与实现类中的属性名bookDao是一致的
- ref:<bean>标签中绑定的id。引用属性采用ref
<BEAN CLASS"COM.ITHEIMA.SERVICE.IMPL.BOOKSERVICEIMPL" ID-"BOOKSERVICE">
<!--给BOOKSERVICEIMPL.的BOOKDAO成员变量赋值,RE于:引用IOC容器中的BOOKDAO
PROPERTY标签:依赖注入,通过SET方法输入
NAME:类中的成员变量名
BOOKSERVICELMPL中有一个私有变量:
REF:注的对象
BOOKDAO
1/业务层实现类
PUBLIC CLASS BOOKSERVICEIMPL IMPLEMENTS BOOK
PRIVATE BOOKDAO BOOKDAO;
<PROPERTY NAME:"BOOKDAO" REF:"BOOKDAO"/>
</BEAN>
PUBLIC VOID SETBOOKDAO(BOOKDAO BOOKDAO)
THIS.BOOKDAO BOOKDAO;
<!--IOC容器创建BOOKDAOIMPL 类的对象-->
<BEAN CLASS-"COM.ITHEIMA.DAO.IMPL.BOOKDAOIMPL" ID-"BOOKDAO"></BEAN>
三、Bean的配置
属性:
id | 唯一标识 | |
class | 类全名 | |
name | 别名,可以使用,; 空格间隔 | |
scope | 作用范围 | |
init-method | 初始执行的方法 | |
destroy-method | 销毁时执行的方法 |
2.1基础配置
●id
●class
●name :给bean取别名
测试类中的调用:getBean("别名")
2.2 bean的作用范围
●scope属性:单例(默认),非单例:每次拿的都是一个新对象(常用)
singleton:单例
prototype:多例
扩展:
●为什么设计成单例: 大多数的类只需要创建一个就够了!
⚫ 适合交给容器进行管理的bean ◼ 控制器对象 (以前用的Servlet做为控制器) ◼ 业务层对象 (如: BookService) ◼ 数据层对象 (如: BookDao或BookMapper) ◼ 工具对象 (如: CartUtils对象) 以上对象都只需要创建一个就够了 ⚫ 不适合交给容器进行管理的bean ◼ 封装实体的域对象(实体类对象 Book 包名: pojo, entity, domain)
2.3 bean的生命周期:
初始化容器
1.创建对象(内存分配)
2.执行构造方法
3.执行属性注入(SET操作)
4.执行BEAN初始化方法
使用BEAN
1.执行业务操作
关闭/销毁容器
1.执行BEAN销毁方法
在<bean>的类中定义:初始化/销毁的时候定义一下其他的功能。
比如在:BookServiceImpl的实现类中定义init();destroy( )方法。
a初始化:init():在无参构造器的后面。
b销毁时候:destroy( ):只对单例模式有效。(需要关闭容器,真正开发中不需要关闭容器 close;registerShutDownHook())
⚫ 关闭容器方式: ◼ 手工关闭容器 :close( )操作 容器.close( ); ◼ 注册关闭钩子,在虚拟机退出前先关闭容器再退出虚拟机 :registerShutdownHook()操作
四、创建对象的三种方式
1无参构造方法(默认)
只要有Bean标签的生成,就会调用无参构造方法!
要保证对象中定义了无参构造方法(当定义了有参构造方法,系统不会自动生成无参构造方法,需要自己创建)。
2静态工厂
方式二:通过工厂的静态方法获取对象
CLASS:指定工厂类
ID:要获取的对象ID
FACTORY-METHOD:指定工厂类中静态方法名字
<BEAN CLASSA"COM.ITHEIMA.UTIL.STATICBOOKFACTORY" ID,"
FACTORY-METHOD "GETBEAN"/>
工厂模式,方法是静态方法
PUBLIC CLASS STATICBOOKFACTORY {
静态方法,返回我们想要的对象
PRETURN
AO GETBEAN(){
PUBLIC STATIC BOOKDAO
RETURN NEW BOOKDAOIMPL();
需要在<bean>标签中定义属性:factory-methods=" "
3实例工厂
工厂模式,方法是实例方法,不是静态方法
PUBLIC CLASS INSTANCEBOOKFACTORY {
<!-方式三:通过工厂对象中实例方法--
成员方法:返回我们想要的对象
<!-1.配置工厂对象 -->
<BEAN CLASS"COM.ITHEIMA.UTIL.INSTANCEBOOKFACTORY" IDS"BOOKFACTORY">
ORETURN
PUBLIC BOOKDAO GETBEAN(){
<1--2.声明BOOKDAO对象
BOOKDAOIMP1();
ID:BEAN的ID
PN NEW
FACTORY-BEAN:实例工厂的ID
FACTORY-METHOD:工厂中方法名
"GETBEAN"ID"BOOKDAO3"/>
<BEAN FACTORY-BEAN"BOOKFACTORY" FACTORY-METHOD-"GETB
需要绑定两个<bean>标签
●先创建工厂对象:<bean class=" " id="name"> 里面定义一个实例方法b1创建实例new一个对象返回。
●调用方法把方法的方法值放到容器:<bean factory-bean=“ name” factory-methods=“b1”>
五、依赖注入
无参构造:当创建对象时候调用。
给成员变量赋值的方法:set/构造器
主要是区分于在bean标签中创建对象的成员属性赋值:
●简单数据类型
●引用数据类型
5.1set注入和构造器注入
针对于有参
名字必须长得一模一样,name来绑定。通常情况使用set注入。
a引用类型 :ref (property name:" "/constructor-arg name:" ")
name:绑定的时候是调用传入构造器的引用类型的名称。如:connectionNumber 和databaseName
b基本数据类型+String :value:
构造器可以根据类型来注入 type;或者是第几个参数 index
5.2自动装配:autoWire
⚫ 自动装配用于引用类型依赖注入,不能对简单类型进行操作 ⚫ 使用按类型装配时(byType)必须保障容器中相同类型的bean唯一,推荐使用 ⚫ 使用按名称装配时(byName)必须保障容器中具有指定名称的bean,因变量名与配置耦合, 不推荐使用 ⚫ 自动装配优先级低于setter注入与构造器注入,同时出现时自动装配配置失效
简单类型不可以自动装配,只服务于引用类型,自动给成员变量赋值。两者默认使用set注入。
●bytype:采用自动类型注入,默认查找在配置文件中:查找引用类型的<bean>,核实的是class,不能有两个同名
<BEAN CLASS:"COM.ITHEIMA.SERVICE.IMPL.BOOKSERVICEIMPL"
ID-"BOOKSERVICE"
相同
AUTOWIRE:"BYTYPE"/
"COM.
CLASS
<BEAN
.IMPL.BOOKDAOIMPL" ID:"BOOKDAO"/>
HEIMA
<!--报错:<BEAN
"COM.ITHEIMA.DAO.IMPL.BOOKDAOIMPL" ID-"BOOKDAO2"/>-->
CLASS
●byname:绑定的是查询视图类中的中<bean> name :如果不匹配就显示为null; 只要是配置了一个bean就会创建一个对象,执行构造方法
<BEAN CLASS:"COM.ITHEIMA.SERVICE.IMPL.BOOKSERVICEIMPL"
名字和属性值不一样
ID-'BOOKSERVICE"
AUTOWIRE:"BYNAME"/>
BOOKDAO
'BOOKDAO1"/
CLASS:"COM.ITHEIMA.DAO.IMPL.BOOKDAOIMPL" ID:"BD"
<BEAN
NAME
"BOOKDAO2"
<BEAN CLASS:"COM.ITHEIMA.DAO.IMPL.BOOKDAOIMPL" ID:"BD1"
NAME
当不匹配时候:java.lang.NullPointerException : 测试类中的bookService.save();
●constructor:使用构造器注入 :绑定的是有参构造函数中的变量名:采用的是byname public BookServiceImpl(BookDao bookDao) { this.bookDao = bookDao; } 当只有一个时候,不区分;如果有多个如果不匹配的化会报错:UnsatisfiedDependencyException
<BEAN CLASS:"COM.ITHEIMA.SERVICE.IMPL.BOOKSERVICEIMPL"
ID"BOOKSERVICE"
'CONSTRUCTOR"
AUTOWIRE
(.IMPL.BOOKDAOIMPL" ID:"BOOKDAO2"
"COM.ITHEIMA.DAO.I
CLASS
AUTOWIRE "CONSTRUCTOR"/>
<BEAN
<BEAN CLASS-.COM.ITHEIMA.DAO.IMPL.BOOKDAOIMPL" IDE"BOOKDAO1" AUTOWIRES"CONSTRUCTRUCTOR"/>->
●byType :在applicationContext中,查找该成员变量的引用类型:<bean class="?">
●byName:按照名字来装配 :查找成员变量的变量名:<bean name="?">
●constructor:按照构造器来注入:绑定有参构造器中传入属性名来配置:判断是否于id匹配。
public 类名(类名 属性名)
●不启动装配
5.3 集合注入(了解)。
c数组注入<array></array>
dList集合<list>
eset集合<set>
fMap集合<map> <entry>
gproperty 属性集<props> <prop>
六、第三方资源配置管理
1管理DataSource连接池对象
a导入依赖:druid、mysql驱动5.1.46
b传入配置文件.properties
c引入配置文件: 导入命名空间:在定义location属性。
<context:property-placeholder location="jdbc.properties"/>
- property-placeholder:引入外部的properties文件
- localtion:有四种定义方法,常用:location="classpath:*.properties":
- system-properties-mode:不使用系统的变量名,怕properties中的key与系统的名称冲突。
d如果是在单元测试里面运行:需要在test目录下创建resourcese;针对于定义:*.properties.
因为它找的是test-classes包下面的resources,如果不配置会爆红。可以看target文件夹。如果是main方法则是里面的classes包。
TEST
JAVA
RESOURCES
TARGET
CLASSES
COM
APPLICATIONCONTEST8.XML
APPLICATIONCONTEXT.XML
APPLICATIONCONTEXT4.XML
APPLICATIONCONTEXT5.XML
APPLICATIONCONTEXT6.XML
APPLICATIONCONTEXT7.XML
JDBC.PROPERTIES
GENERATED-SOURCES
LGENERATED-TEST-SOURCES
TEST-CLASSES
COM
JDBC.PROPERTIES
M
POM.XML
<!--引入外部的PROPERTIES文件-->
<CONTEXT:PROPER
HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/CO
PROPERTY-PLACEHOLDER
HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA
创建DPROPERTIES
HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/CO
CLPROPERTY-OVERRIDE
<BEAN
XML复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!--property-placeholder标签:引入外部的properties文件
location属性: 指定外部properties文件的位置
system-properties-mode属性: NEVER, 不加载系统的属性
location="jdbc.properties,msg.properties": 加载多个配置文件中间用,分割
location="*.properties": 加载所有的properties文件, 单元测试找编译后test-classes里面的配置, main方法运行找classes里面的配置(类路径)
location="classpath:*.properties": 加载所有的properties文件, 单元测试找编译后test-classes里面的配置, main方法运行找classes里面的配置(类路径)
location="classpath*:*.properties": 会去依赖的jar中找properties文件
-->
<context:property-placeholder location="classpath*:*.properties" system-properties-mode="NEVER"/>
<!--创建DruidDataSource放到IoC容器中-->
<bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
</beans>
2加载properties属性文件
开启CONTEXT命名空间
<?XML VERSION-"1.0" ENCODING-"UTF-8"?>
<BEANS XMLNS:"HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/BEANS"
`TTP://WWW.W3.ORG/2001/XMLSCHEMA-INSTANCE"
XMLNS:XSI
XMLNS:CONTEXT-"HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/CONTEXT"
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">
</BEANS>
使用CONTEXT命名空间,加载指定PROPERTIES文件
输入命名空间会自动导入
<CONTEXT:PROPERTY-PLACEHOLDER LOCATION-"JDBC.PROPERTIES"/>
使用$心读取加载的属性值
<PROPERTY NAME-"USERNAME" VALUE-"${JDBC.USERNAME}"/>
不加载系统属性
" SYSTEM-PROPERTIES-MODE-"NEVER"/>
<CONTEXT:PROPERTY-PLACEHOLDER LOCATION-"JDBC.PROPERTIES" SYS
加载多个PROPERTIES文件
<CONTEXT:PROPERTY-DLACEHOLDER LOCATION-"IDBC.PROPERTIES,MSG.PROPERTIES"/
加载所有PROPERTIES文件
<CONTEXT:PROPERTY-PLACEHOLDER LOCATION-"2
PROPERTIES"/>
加载PROPERTIES文件标准格式(常用)
<CONTEXT:PROPERTY-PLACEHOLDER LOCATION-"CLASSPATH:*.PROPERTIES"/>
从类路径或JAR包中搜索并加载PROPERTIES文件
<CONTEXT:PROPERTY-PLACEHOLDER LOCATION-"CLASSPATH*:*.PROPERTIES"/>
常见异常
1.applicationContext.xml中的别名不存在,或者是id不存在
没有找到BEAN异常
没有B5这个名字
I
ORG:SPRINGTRAMENORK. BEANS:FACTORY.SROSUCHIBEANDEFENILLIUNEXCEDTLUN, NO BEALI IAMED "US AVAFLABLE
2.no default constructor found
ING BEAN WITH NAME 'BOOKDAO'
ISED BY:OFG,SPRENGTRANEWORK,BEANS,TASTORY:BEANG DENEREATLONEXCEPFIOD VEALE DREANS,TAR OREATING DEN
CAUSED
E LAPPLICATIONCONTEXT:XNLJ: INSTANTIATION OF BEAN FAILED; NESTED EXCEPTION IS ORG-SPRINGTRAMEWORK
DEFINED IN CLASS PATH RESOURCE LA
创建对象失败,没有找到无参构造器
NESTED EXCEPTION IS JAVA,TANG NOSUCHNETHODEXCEPTION: COM,ITHEIMA.DAG.IMPL.BOOKDAOIMPL.CINIT>ONIT>O
3.多个同名的数据类型
按类型自动装配,但是容器中有多个相同类型的对象
若有收获,就点个赞吧