Spring学习视频地址
1.腾讯学堂 DT https://ke.qq.com/course/list/DT
2.https://www.iqiyi.com/v_19rqzlu6so.html#curid=1290279300_fd92b49e8db19d199225e9948b800d2e
--------------------------------------------------------------------------------------------------
Spring
IOC:控制反转(ID:依赖注入)
AOP
1.搭建Spring环境
下载jar包
http://maven.springframework.org/release/org/springframework/spring/
dist中放的是二进制 docs中放的是文档
选择的是:spring-framework-4.3.9.RELEASE-dist.zip
开发spring至少需要使用的jar(5个+1个):
spring-aop.jar 开发AOP特性时需要的jar
spring-beans.jar 处理Bean的jar <bean>
spring-context.jar 处理spring上下文的jar <content>
spring-core.jar spring核心jar
spring-expression.jar spring表达式
三方提供的日志jar(搜索commons-logging.jar mvn)
commons-logging.jar 日志
2.编写配置文件
方式一 :增加sts插件
为了编写时有一些提示、自动生成一些配置信息,可以给Eclipse增加支持spring的插件:spring tool suite
http://spring.io/tools/sts/all
下载spring-tool-suite-3.7.2.RELEASE-e4.5.1-win32-x86_64.zip,
然后在eclipse中安装:help-Install new SoftWare.. Add
方式二:直接下载sts工具(相当于一个集合了Spring tools的Eclipse):http://spring.io/tools/sts/
新建:bean configuration..- applicationContext.xml
3.开发Spring程序(IOC)
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml);
//执行从springIOC容器中获取一个id为student的对象
Student student = context.getBean("student");
可以发现,springIOC容器帮我们new了一个对象,并且给对象赋了值
(SpringIOC容器:1.创建对象,2.给对象的属性赋值)
SpringIOC的发展史:
1.new、setXxx()
Studet student = new Student();
student.setXxx();
2.
简单工厂
通过简单工厂,可以将创建课程new集中起来操作,方便后期维护
弊端:1.自己写工厂 2. 不够彻底
3.
IOC(超级工厂):可以存放任何对象
IOC(控制反转)也可以称之为DI (依赖注入):
控制反转 :将创建对象、属性值的方式进行了翻转,从new,setXxx() 翻转为了从springIOC容器getBean()
依赖注入:将属性值,注入给了属性,将属性注入给了bean,将bean注入了IOC容器
总结:IOC/id,无论要什么对象,都可以直接去springioc容器中获取,而不需要自己操作(new\setXxx)
因此之后的IOC分为2步:
1 先给springioc中存放对象并赋值
2 拿
DI:依赖注入
Teacher
course:cname teacher
IOC容器赋值:如果是简单类型(8个基本+String):value,
如果是对象类型,ref="需要引用的ID值",
因此实现了对象与对象之间的依赖关系
conext.getBean(需要获取的bean的ID值)
依赖注入的3中方式:
1.set方式:通过setXxx()赋值
赋值,默认使用的是set方法();
依赖注入底层是通过反射实现的。
<property name="" value=""></property>
2.构造器注入:通过构造方法赋值
<constructor-arg value="" type="" index="" name=""></constructor-arg>
需要注意:如果<constructor-arg>的顺序与构造方法参数的顺序不一致,则需要通过type或者index或者name指定顺序。
3.p命名空间注入
引入p命名空间
xmlns:p="http://www.springframework.org/schema/p"
<bean id="course" class="org.lanqiao.entity.Course" p:courseHour="300" p:courseName="hadoop" p:teacher-ref="teacher">
简单类型:
p:属性名= "属性值"
引用类型(出来String外):
p:属性名-ref = "引用的id"
注意多个p赋值的时候要有空格、
注意:
无论是String还是Int/short/long,在赋值时都是value="值",
因此建议此种情况需要配合name/type进行区分
实例
注入各种数据类型:List Set map properties
List、Set、数组 各自都有自己的标签<set> <list> <srray>,但是也可以混着用
给对象类型赋值null:
<property name="name">
<null/> --> 注意 没有<value>
</property>
赋空值""
<property name="name">
<value></value>
</property>
在ioc中定义bean的前提,该bean的类必须提供了无参构造
自动装配:(只适用于ref类型)
约定优于配置
<bean id="" class="" autowire="byName|byType|constructor"> byName:本质是byId
byName:自动寻找:其他的bean的id值-该类的属性名
byType:其他bean的类型(class)是否与该类的ref属性类型一致
(注意,此种方式,必须满足:当前IOC容器中只能有一个Bean满足条件)
constructor:其他bean的类型(class)是否与该类的构造方法参数的类型一致:此种方式的本质就是byType
可以在头文件中一次性将ioc容器的所有bean统一设置成自动装配;
<beans xmlns="http://www.springframework.org/schema/beans"
...
default-autowire="byName"
>
自动装配虽然可以减少代码量,但是会降低程序的可读性,使用时需要谨慎。
使用注解定义bean:通过注解的形式将bean以及相应的属性值放入IOC中
<context:component-scan base-package="org.lanqiao.dao">
</context:component-scan>
Spring在启动的时候,会根据base-package在该包中扫描所有类,查找这些类是否有注解@Component("studentDao"),如果有,则将该类加入spring IOC容器。
@Component细化:
dao层注解:@Repository
service层注解:@Service
controller控制层注解:@Controller
使用注解实现事物(声明式事物)
目标:通过事物使以下方法要么全成功、要么全失败
public void addStudent(){
//增加班级
//增加学生
//crdu
}
a.jar包
spring-tx-4.3.9.RELEASE.jar
spring-jdbc-4.3.9.RELEASE.jar
ojdbc.jar
commons-dbcp.jar 连接池使用到数据源
commons-pool.jar 连接池
aopalliance.jar
b.配置
jdbc\mybatis\spring
增加事物tx的命名空间
<!--增加对事务的支持-->
<tx:annotation-driven transaction-manager="txnManager"/>
c.使用
将需要成为事务的方法前增加注解:
@Transactional(readOnly=false ,propagation= Propagation.REQUIRED)
------------------------------------------------------
2.AOP:面向方面编程
一个普通的类 --> 有特定功能的类
a.继承类 b.实现接口 c.注解 d.配置
public class MyFilter extends/implements Xx{}
一、类 --> "通知":实现接口
前置通知实现步骤:
a.jar
aopaliance.jar
aspectjweaver.jar
b.配置
c.编写
aop:每当之前add()之前 自动执行一个方法
addStudent():业务方法(IStudentService. java 中的 addStudent())
before():自动执行的通知,即aop前置通知
如果出现异常:类似java.lang.NOClassDefFoundError:.....
则说明缺少jar
后置通知:
a.通知类,普通实现接口
b.业务类、业务方法
StudentServiceImpl中的addStudent()
c.配置
将业务类、通知纳入springIOC容器
定义切入点(一段)、定义通知类(另一端),通知pointcut-ref将两端连接起来
异常通知(发生异常):
根据异常通知接口的定义可以发现,异常通知的实现类必须编写以下方法:
public void afterThrowing([Method, args, target], ThrowableSubclass)
该方法只有两种情况:
a情况:public void afterThrowing(Method, args, target, ThrowableSubclass)
b情况:public void afterThrowing(ThrowableSubclass)
环绕通知:在目标方法的前后,异常发生时、最终等各个地方都可以进行的通知,最强大的
通知:可以根据获取目标放的全部控制权(目标方法是否执行、执行之前、执行之后、参数、返回值等)
在使用环绕通知时,目标方法的一切信息 都可以通过invocation参数获取到
环绕通知底层是通过拦截器实现的
二、实现注解实现通知(aop)
a.jar
与实现接口的方式相同
b.配置
将业务类、通知纳入springIOC容器
开启注解对于AOP的支持:<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
业务类addStudent - 通知
c.编写
通知
@Aspect //声明该类是一个通知
public class logBeforeAnnotation {
}
注意:通过注解形式将对象增加到ioc容器时,需要设置扫描器
<context:component-scan base-package="org.lanqiao.aop"></context:component-scan>
扫描器会将指定的包中的@Component @Service @Respository @Controller 修饰的类产生的对象增加到AOC容器中
@Aspect不需要加入扫描器,只需要开启即可:<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
只有使用@Component("logAnnotation")注解时候才必须开启扫描器
通过注解形式实现aop,如果想获取目标对象的一些参数,则需要使用一个对象:JoinPoint
注解形式的返回值问题:
a.声明返回值的参数名:
@AfterReturning(pointcut="execution( public * addStudent(..))",returning="returnValue")
public void myAfter(JoinPoint jp,Object returnValue) {//returnValue是返回值,但需要告诉spring
System.out.println("注解形式-后置通知:目标对象:"+jp.getTarget()+",方法名:"+jp.getSignature().getName()+",参数列表:"+Arrays.toString(jp.getArgs())+",返回值:"+returnValue);
}
注解形式实现aop时,通知的方法不能多不能少
实现接口形式、注解形式 只捕获声明的特定类型的异常,而其他类型异常不捕获。
catch()
三、通过 配置 将 类--->通知
基于schema配置
类似与实现接口的方式
接口方式通知:public class LogAfter implements AfterReturningAdvice
Schema方式通知:
a.编写一个普通类 public class LogAfter{}
b.将该类通过配置,转为一个"通知"
如果要获取目标对象信息:
注解、schema(配置):JoinPoint
接口:Object returnValue, Method method, Object[] args, Object target
schema形式 和注解形式相似,不同之处:注解形式使用了注解@after,schema形式进行了多余的配置
Spring容器初始化:1.将IOC容器中的所有bean实例化为对象 new对象
2.将各个bean依赖的属性值注入进去 属性赋值
spring容器实例化在java程序中:ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
=====================================================================
1.Spring开发开发WEB项目及拆分Spring配置文件
a. web项目如何初始化SpringIOC程序:思路,当服务器启动(tomcat),通过监听器将SpringIOC初始化一次(该监听器spring-web.jar)
因此用spring开发web项目需要7个jar:spring-java的6个jar+spring-web.jar
注意:web项目的jar包是存入到WEB-INF/lib中
web项目启动时,会自动加载web.xml,因此需要在web.xml中加载监听器(ioc容器初始化)。
web项目启动时,启动实例化IOC容器
<!-- 指定IOC容器(applicationContext.xml)的位置 -->
<context-param>
<!-- 监听器的父类ContextLoader中有一个属性contextConfigLocation,该属性值保存着容器配置文件applicationContext.xml的位置 -->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<!-- ctrl+shirt+T搜索 ContextLoaderListener-->
<!-- 配置spring-web.jar提供的监听器,此监听器可以在服务器启动时初始化IOC容器 。
初始化IOC容器(applicationContext.xml),
1.必须告诉监听器此容器的位置:context-param
2.默认约定的位置:WEB-INF/applicationContext.xml
-->
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
b.拆分Spring配置文件
java项目:applicationContext1.xml
applicationContext.xml
applicationContext.xml
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext2.xml");
用到哪个就调用哪个
Web项目:
根据什么拆分?
i.三层结构
UI(html/css.jsp/servlet) applicationController.xml
Service:applicationService.xml
Dao:applicationDao.xml
公共数据库:applicationDB.xml
ii.功能结构
学生相关的配置 applicationContextStudent.xml <bean id="" class="X...Student"></bean>
班级相关配置 applicationContextClass.xml
合并:如何将多个配置文件加载
(1) <context-param>
<!-- 监听器的父类ContextLoader中有一个属性contextConfigLocation,该属性值保存着容器配置文件applicationContext.xml的位置 -->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml,
classpath:applicationContext-Dao.xml,
classpath:applicationContext-Service.xml,
classpath:applicationContext-Controller.xml
</param-value>
</context-param>
(2)推荐
<context-param>
<!-- 监听器的父类ContextLoader中有一个属性contextConfigLocation,该属性值保存着容器配置文件applicationContext.xml的位置 -->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml,
classpath:applicationContext-*.xml,
</param-value>
</context-param>
(3)只在web.xml中加载主配置文件,
<param-value>
classpath:applicationContext.xml,
</param-value>
然后在主配置文件中加载其他配置文件
<import resource="applicationContext-Controller.xml"/>
<import resource="applicationContext-Dao.xml"/>
<import resource="applicationContext-Service.xml"/>
总结:bean的实例化,DI是在保存在SpringIOC容器中;
但是每一次request是请求Servlet容器。
2.Spring整合MyBatis
整合思路:
SqlSessionFactory -> SqlSession ->StudentMapper ->CRUD
可以发现,MyBatis最终是通过SqlSessionFactory来操作数据库,
Spring整合MyBatis 其实就是将MyBatista的SqlSessionFactory交给Spring
整合步骤:
1.jar
mybatis-spring.jar 整合MyBatista和spring的jar包
spring-tx.jar
spring-jdbc.jar
spring-expression.jar
spring-context-support.jar
spring-core.jar
spring-context.jar
spring-beans.jar
spring-aop.jar
spring-web.jar
commons-logging.jar
commons-dbcp.jar
ojabc.jar 操作数据库jar
mybatis.jar
log4j.jar
commons-pool.jar
2.类-表
3.MyBatis配置文件conf.xml
4.通过mapper.xml将类、表建立映射关系
5.
之前使用conf.xml -> SqlSessionFactory
现在整合的时候。需要通过Spring管理SqlSessionFactory,因此产生SqlSessionFactory所需要的数据库信息
配置spring配置文件(applicationContext.xml)
6.使用Spring-MyBaties整合产物开发程序
目标:通过spring产生 mybaties最终操作需要的动态mapper对象(StudentMapper)
Spring产生动态mapper对象有3种方法
a.第一种方式
DAO层实现类 继承 SqlSessionDaoSupport类
SqlSessionDaoSupport类提供了一个属性SqlSession
b.第二种方式
就是省略掉第一种方式的实现类
直接MyBatis提供的Mapper实现类:org.myBatis.spring.mapper.MapperFactoryBean
缺点:每一个mapper都需要一个配置一次
c.第三种方式
批量配置实现类
=================servlet与SpringIoc容器,及两者之间的桥梁======================