0、Spring概述
0.0、什么是Spring
Spring是一个以IOC(控制反转)和AOP(面向切面编程)为内核的框架。IOC是Spring的基础,简单地说,就是以前调用new构造函数方法来创建对象,现在变成成使用Spring来创建对象。DI(依赖注入)与IOC的含义相同,从两个角度来描述同一个概念。简单的说,DI就是对象的属性,已经被注入好相关的值,直接使用即可。
0.1、Spring概述
Spring是分层的JavaSE/EE应用full-stack轻量级开源框架,以IOC(Inverse Of Control:反转控制)和AOP(Aspect Oriented Programming:面向切面编程)为内核,提供了展现层Spring MVC和持久层Spring JDBC以及业务层事务管理等众多的企业级应用技术,还能整合开源世界众多著名的第三方框架和类库,逐渐成为使用最多的JavaEE企业应用开源框架。
0.2配置小结
0.2.1、POM.XML配置
<dependencies>
<!--提供在IOC基础上扩展的功能-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<!-- 解析切入点表达式-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.7</version>
</dependency>
<!--Spring Jdbc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<!--Spring事务-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
</dependencies>
0.2.2、配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!-- 告知spring在创建容器时要扫描的包,配置所需要的标签不是在beans约束中
而是一个名称为context名称空间和约束,会扫描所有注解
-->
<context:component-scan base-package="com.itheima"></context:component-scan>
<!--开启aop-->
<aop:aspectj-autoproxy/>
==============配置Bean===============
<!--<bean id="user" class="com.domain.User"></bean>-->
<!--<bean id="userFactory" class="com.Factory.Factory">-->
<!--</bean>-->
<!--<bean id="user" factory-bean="userFactory" factory-method="getUser"></bean>-->
<!--<bean id="accountDao" class="com.Dao.AccountDaoImpl">-->
<!--</bean>-->
<!--<bean id="accountService" class="com.Service.AccountServiceImpl" scope="prototype"></bean>-->
<!--<bean id="accountService" class="com.Service.AccountServiceImpl">-->
<!--<constructor-arg name="name" value="zhoujian"></constructor-arg>-->
<!--<constructor-arg name="age" value="11"></constructor-arg>-->
<!--<constructor-arg name="birthday" ref="now"></constructor-arg>-->
<bean id="accountService" class="com.Service.AccountServiceImpl">
<property name="list" >
<!-- 注入List数据集合-->
<list>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
</list>
</property>
<!-- 注入String[]数据集合-->
<property name="str">
<array>
<value>1</value>
<value>2</value>
<value>3</value>
</array>
</property>
<!-- 注入Set数据集合-->
<property name="set">
<set>
<value>1</value>
<value>2</value>
</set>
</property>
<property name="map">
<map>
<entry key="1" value="2"></entry>
<entry key="2" value="3"></entry>
</map>
</property>
</bean>
<!--</bean>-->
<bean id="now" class="java.util.Date"></bean>
<bean id="dao" class="com.Dao.AccountDaoImpl"></bean>
<!--配置账户的持久层-->
<bean class="com.itheima.dao.Impl.AccountDaoImpl" id="accountDao">
<!--注入数据库操作模板-->
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>
<!--配置JDBCTemplate,数据库操作模板-->
<bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate">
<!--注入数据源-->
<property name="dataSource" ref="ds"></property>
</bean>
<!--配置数据源-->
<bean id="ds" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/eesy?useUnicode=true&characterEncoding=UTF-8&userSSL=false&serverTimezone=GMT%2B8"></property>
<property name="username" value="root"></property>
<property name="password" value="123456"></property>
</bean>
<!-- 1、配置Logger类,可以增强的方法-->
<bean id="logger" class="com.itheima.utils.Logger"></bean>
<!--2、配置aop-->
<aop:config>
<!-- 使用 aop:aspect表明开始配置切面 -->
<aop:aspect id="logAdvice" ref="logger">
<!--配置通知的类型并且建立通知方法和切入点方法的关联,实现增强-->
<aop:before method="beforeprintLog" pointcut="execution( * com.itheima.service.Impl.*.*(..))"></aop:before>
<!--配置后置通知和异常通知只能运行一个-->
<aop:after-returning method="afterReturingprintLog" pointcut="execution( * com.itheima.service.Impl.*.*(..))"></aop:after-returning>
<!--配置异常通知-->
<aop:after-throwing method="afterThrowingprintLog" pointcut="execution( * com.itheima.service.Impl.*.*(..))"></aop:after-throwing>
<!--配置最终通知-->
<aop:after method="afterprintLog" pointcut="execution( * com.itheima.service.Impl.*.*(..))"></aop:after>
<aop:after method="afterprintLog" pointcut-ref="pt1"></aop:after>
<!-- 配置切入点表达式 id属性用于指定表达式唯一标志。expression属性用于指定表达式内容
此标签写在aop:aspect标签内部只能当前切面使用,
它还可以写在aop:aspect外面,此时就变成了所有切面可用
-->
<aop:pointcut id="pt1" expression="*com.itheima.service.Impl.*.*(..)"></aop:pointcut>
<!-- 配置环绕通知 详细的注释请看Logger类中-->
<aop:around method="aroundPrintLog" pointcut="execution( * com.itheima.service.Impl.*.*(..))"></aop:around>
</aop:aspect>
</aop:config>
</beans>
0.3、Spring的优势
方便解耦,简化开发
通过Spring提供的IOC容器,可以将对象间的依赖关系交由Spring进行控制,避免硬编码所造成的过度程序耦合。用户也不必再为单例模式类,属性文件解析等这些底层的需求编写代码,可以更加专注于上层的应用。
AOP编程的支持
> 通过Spring的AOP功能,方便进行面向切面的编程,许多不容易用传统的OOP实现的功能可以通过AOP轻松应付。
声明是事务的支持
>可以将我们从单调烦闷的事务管理代码中解脱出来,通过声明方式灵活的进行事务的管理,提高开发的效率和质量。
方便集成各种优秀的框架
>Spring可以降低各种框架的使用难度,提供了对各种优秀框架(Structs、Hibernate、Hessian、Quartz等)的直接使用。
1、程序的耦合和解耦
1.1、什么是程序的耦合
1.2、解决程序耦合的思路
1.3、工厂模式解耦
在实际开发中我们可以吧三层的对象都使用配置文件配置起来,当启动服务器应用加载时,让一个类中的方法通过读取配置文件,吧这些对像创建并存起来,在接下来使用的时候,直接拿过来使用就好了
那么读取配置文件,创建和获取三层对象的类就是工厂
自己写的工厂类
1.4、控制反转(IOC)
这种被动接受的方式是获取对象的思想就是控制反转,它是Spring框架的额核心之一
1.5、控制反转的另外一种解释
在面向对象传统编程方式中,获取对象的方式通常是用new关键字主动创建一个对象。Spring中的IOC方式对象的生命周期由Spring框架提供的IOC容器来管理,直接从IOC容器中获取一个对象,控制权从应用程序交给了IOC容器
IOC理论上借助于“第三方”实现具有依赖关系对象之间的耦合,即把各个对象类封装之后,通过IOC容器来关联这些对象类.这样对象与对象之间就通过IOC容器进行联系,而对象与对象之间没有直接的联系
应用程序在没有引入IOC容器之前,对象A依赖对象B,那么对象A在实例化或者运行到某一点的时候,自己必须主动创建对象B,其中无论是创建还是使用自己创建的对象B,控制权都在应用程序自身。如果应用程序引入了IOC容器之后,对象A和对象B之间失去了直接联系,那么当对象A实例化和运行时,如果需要对象B,IOC容器就会主动创建一个对象B注入(依赖注入)到对象A所需要的地方。由此,对象A获得依赖对象B的过程,由主动形为变为被动行为,即把创建对象交给了IOC容器处理,控制权颠倒过来了,这就是所谓的控制倒转
2、使用Spring的IOC解决程序耦合的问题
Spring框架的主要功能是通过其核心容器来实现的。Spring框架提供的两种核心容器分别是:BeanFactory和ApplicationContext。
2.1配置的简单使用
2.1.1配置bean.xml
2.1.2测试配置是否成功
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HU0nYwIr-
2.2Spring基于XML的IOC细节
2.2.1、Spring中工厂类,创建容器的类
在Spring中创建容器,也就是利用工长的方式创建一个Map很重要,对于不同的场景下存在不同创建容器(Container)的工厂类,下面我们做一个梳理。
BeanFactory采用了工厂设计模式,即Bean容器模式,负责读取Bean的配置文件,管理对象的生成、加载,维护Bean对象与Bean对象之间的依赖关系,负责Bean的生命周期。对于简单的应用程序来说,使用BeanFactory就已经足够管理Bean了。
2.2.2BeanFactory和ApplicationContext的接口区别
BeanFactory才是Spring容器的中的顶层接口
ApplicationContext是他的子接口
2.2.3ApplicationContext接口的实现类
配置文件包含Bean的id、类、属性及其值,包含一个元素和数个子元素。Spring IOC框架可根据Bean的id从Bean配置文件取得该Bean类,并生成该类的一个实例对象,继而从配置文件中获得该对象的属性和值
2.3、IOC中Bean标签和管理对象的细节
2.3.1Bean标签
2.3.2、Bean标签的作用范围
2.3.3Bean标签的生命周期
2.3.4实例化Bean标签的三种方式
(1)使用默认无参构造函数
(2)Spring管理静态工厂-使用静态工厂的方法创建对象
(3)Spring管理实例工厂-使用实例工厂的方法创建对象
3、Spring的依赖注入
3.1、依赖注入的概念
依赖注入:Dependency Injection.它是Spring框架核心ioc的具体表现
我们在编写程序时,通过控制反转,把对象的创建交给了Spring,但是代码中不可能出现没有依赖的情况。ioc解耦只是降低他们的依赖性,但不会消除。例如:我们的业务层仍会调用持久层的方法
那种业务层和持久层的依赖关系,在使用Spring之后,就让Spring来维护了>
简单来说,就是坐等框架把持久层对象传入业务层,而不用我们自己去获取
DI是Dependecy Inject的缩写,译为“依赖注入”。所谓依赖注入,就是由IOC容器在运行期间动态地将某种依赖关系注入对象之中。例如,将对象B注入(注销)给对象A的成员变量。
事实上,依赖注入(DI)和控制反转(IOC)是对同一件事情的描述,从某个方面讲,就是他们描述的角度不同。依赖注入时从应用程序的角度描述,即应用程序依赖容器创建并注入它所需要的外部资源:而控制反转是从容器的角度描述,即容器控制应用程序,由容器反向地向应用程序注入应用程序所需要的外部资源。
如前所述,依赖注入(DI)和控制反转(IOC)是对同一件事情的不同描述。依赖注入的作用是在使用Spring框架创建对象时,动态的将其所依赖的对象注入Bean组件中,其通常实现方式有两种:一种是属性setter()方法注入;另一种是构造方法注入
属性setter()方法注入:IOC容器使用setter()方法注入被依赖的实例。
通过调用无参构造器或无参静态构造方法实例化Bean后,调用Bean的setter()方法,即可实现基于setter()方法的依赖注入。
该方法简答,直观,而且容易理解,所以Spring的设置注入被大量使用。
构造方法注入:IOC容器使用构造方法注入被依赖的实例,基于构造方法的依赖注入通过调用带参数的构造方法来实现,每个参数代表一个依赖。
3.2、构造函数注入
3.3、set方法注入
3.4注入集合属性
顾名思义,就是给类中的集合成员传值,它用的是set方法注入的方式,只不过变量的数据类型都是集合。
4、Bean的配置总结
4.1、Bean的配置
Spring如同一个工厂,由于生产和管理Spring容器中的Bean。要使用这个工厂,需要开发者对Spring的配置文件进行配置。在实际开发中,最常采用XML格式的配置方式,即通过XML文件夹注册并管理Bean之间的依赖关系。
在Spring中,XML配置文件的跟元素是,中可以包含多个子元素,每一个子元素定义了一个Bean,并描述了该Bean如何被装配到Spring容器中。子元素中包含多个属性
属性或子元素名称 | 说明 | |
---|---|---|
id | Bean的唯一标志符,Spring容器对Bean的配置、管理都通过该属性进行。 | |
name | Spring容器通过此属性进行配置和管理 | |
class | 指定Bean的实现类,它必须使用类的全限定名 | |
scope | 用于设定Bean实例的作用域,其属性值有singleton(单例)、prototype(原型)、request、Session、gloable、application和webSocket | |
property | 元素的子元素,用于调用Bean实例中的setter()方法完成属性赋值。从而完成依赖注入。钙元素的name属性指定Bean实例中的相应属性名,ref属性或value属性用于指定参数值 | |
constuctor-arg | 元素的子元素,可以使用此元素传入构造参数进行实例化。该元素的index属性指定构造参数的序号(从0开始),type属性指定构造参数的类型,参数值可以通过ref或value子元素指定 | |
ref | 、等元素的属性或子元素,可以用于指定对Bean工厂中某个Bean实例的引用 | |
value | 、等元素的属性或子元素,可以直接用于给定一个常量值 | |
list | 用于封装List或数组属性的依赖注入 | |
set | 用于封装Set类型属性的依赖注入 | |
map | 用于封装Map类型属性的依赖注入 | |
entry |
4.2Bean的装配方式
Bean的装配方式可以理解为依赖关系注入,Bean的装配方式即Bean依赖注入方式。Spring容器支持多种形式的Bean装配方式,如基于XML的装配、基于Annotation(注解)的装配和自动装配等。
建议在自己的工程中所开发的类尽量使用注解的方式,因为使用它并不困难,甚至可以说更为简单,而对于引用第三方包或者服务的类,尽量使用XML方式,这样的好处是可以尽量对第三方包或者服务的细节减少理解,也更加清晰和明朗。<b推荐使用XML+注解的混合开发**
4.2.1、基于XML的装配/注入依赖
基于XML装配的的头文件
Spring提供了两种基于XML的装配方式:设置注入(Setter Injection)和构造注入(Constructor Injection).
在Spring实例化Bean的过程中,Spring首先会调用Bean的默认构造方法来实例化Bean对象,然后通过反射的方式调用setter()方法来注入属性值。因此,设值注入要求一个Bean必须满足以下两点要求:
-
Bean类必须提供一个默认的无参构造方法。
-
Bean类必须为需要注入的属性提供对应的setter()方法。
使用设置注入时,在Spring配置文件时需要使用元素的子元素来为每个属性注入值;而使用构造注入时,在配置文件中需要使用元素的子元素来定义构造方法的参数,可以使用其value属性来设定值。
4.2.2基于注解的装配/依赖注入
以下的为半自动注解的方式,即必须拥有配置文件bean.xml;为了实现全自动往往需要有一个配置类,详情见4.2.3
基于注解装配的头文件
注意多了个context
为了自动检测匿名的包,需要添加<context:component-scan base-package>
在装配中,尽管使用XML配置文件可以实现Bean的装配工作,但如果应用中有很多Bean就会导致XML配置文件过于臃肿,给以后的维护和升级工作带来一定的困难。为此,Spring提供了对Annotation技术的全面支持。
注解名称 | 说明 | |
---|---|---|
@Component | 可以使用此注解描述Spring中的Bean,但它是一个泛华的概念,仅仅表示一个组件(Bean),并且可以作用在任何层次。使用时只需要将该注解标注在响应的类即可。 | |
@Repository | 用于将数据访问层(DAO层)的类标志位Spring中的Bean,其功能与@Component相同 | |
@Service | 通常作用在业务层(Service)层,用于将业务层的类标志位Spring中的Bean,其功能与@Component相同 | |
@Controller | 通常作用在控制层(如Spring MVC的controller),用于将控制层的类标志位Spring中的Bean,其功能与@Component相同 | |
@Autowired | 用于对Bean的属性变量、属性的setter()方法及构造方法进行标注,配合对应的注解处理器完成Bean的自动装配工作,默认按照Bean的类型进行装配 | |
@Qulifier | 与@Autowired注解配合使用,会将默认的按Bean类型装配修改为按Bean的实例名装配,Bean的实例名称由@Qualfier注解的参数指定 | |
@Resource | 其作用于@Autowired一样,区别在于@Autowired默认按照Bean类型装配,而@Resource默认按照Bean的实例名称装配。@Resource中有两个重要属性:name和type。Spring将Name属性解析为Bean的实例名称,type属性解析为Bean的实例类型。若指定name属性,则按照实例名称进行装配;若指定type属性,则按Bean类型进行装配;若都不指定,则先按照Bean实例名称,不能匹配时在按照Bean类型进行装配。 |
一般情况下,采用自动注入依赖的方式@Autowired。
用于创建对象
用于依赖注入
用于改变生命周期
总结: