写在前面:我越深一步学习Spring越会体验到人类智慧的伟大。Spring框架真的是有很多妙用,尤其是IOC和AOP两种思想,再深入学习可以看源码,非常有用,可以帮助你理解。
Spring
1.Spring概述
1.1:Spring框架概念:
框架的学习方法:框架是一个软件,是其他人写好的软件,
1)需要了解框架能做什么,mybatis–访问数据库,对表中数据进行增删改查
2)框架的语法,框架要完成一个功能,需要经过一些步骤支持。
3)框架的内部实现,框架内部怎么做,原理是什么。
4)通过学习,可以实现一个框架
出现在2002年左右,解决企业开发的难度,减轻对项目模块之间的管理,类与类之间的管理,管理对象间的关系。核心技术:ioc(控制反转),aop(面向切面编程)。能实现模块和类之间的解耦合。
依赖:classA使用classB的属性或方法,叫做classA依赖classB
1.2:Spring框架优点:
1.轻量,所需jar包比较小
2.针对接口编程,解耦合
3.AOP:面向切面编程
4.能够集成其他框架,可以集成其他框架,一同完成一个项目
1.3:Spring体系结构
数据访问模块 web开发模块(Springmvc)
AOP 和Aspects Instrumentation Messaging(消息发送)
核心容器
2.IOC控制反转
2.1:IOC思想描述:
把对象的创建,赋值,管理工作都交给代码之外的容器实现,也就是对象的创建时有其他外部资源完成。
控制:创建对象,对象的属性赋值,对象之间的关系管理
反转:把原来开发人员管理,创建对象的权限移交给代码之外的容器实现,也就是对象的创建时是有其他外部资源完成
正转:开发人员在代码中,使用new创造方法创建对象,开发人员主动管理对象
容器:可以是一个服务器软件,一个框架
使用IOC目的:减少对代码的改动也能实现不同的功能
ioc技术实现:
DI(依赖注入)是ioc的技术实现:只需要在程序中提供要使用的对象的名称,至于对象如何在容器中创建,赋值,查找,都由容器内部实现。
Spring是使用DI实现了ioc的功能,使用的是反射机制
2.2:Spring第一个程序
使用spring容器创建的对象
1.指定spring配置文件的名称
String config=“beans.xml”
2.创建表示spring容器的对象,ApplicationContext
ApplicationContext表示Spring容器,通过容器获取对象
ClassPathXmlApplicationContext:表示从类路径中加载spring的配置文件
从容器中获取某个对象,调用对象方法
getbean获取配置文件中的id值
使用对象
String config="beans.xml";
ApplicationContext ac=new ClassPathXmlApplicationContext(config);
SomeService service=(SomeService) ac.getBean("someService");
service.dosome();
查看创建对象的数目和名称
int nums=ac.getBeanDefinitionCount();
System.out.println(nums);
String names []=ac.getBeanDefinitionNames();
for(String name:names){
System.out.println(name);
非自定义对象
public void test04(){
String config="beans.xml";
ApplicationContext ac=new ClassPathXmlApplicationContext(config);
Date my = (Date) ac.getBean("mydate");
System.out.println("当前时间为"+my);
2.3 对对象的属性进行赋值
1.set注入
在配置文件中
简单类型:
<bean id="mystudent" class="com.bjpowernode.ba01.Student">
<property name="name" value="电棍"/>
<property name="age" value="20"/>
</bean>
2.引用类型set注入
<property name="属性值名" ref="bean的id";
set的注意事项,
1.先spring会调用类的无参构造方法创建对象再对其赋值
2.要在class中写set方法
3.方法里面是由开发人员决定的
只要有set就会执行
3:构造注入
spring调用有参数方法构造方法
1.的name属性,name表示构造方法的形参名
2.的index属性,index表示构造方法形参的位置
4:引用类型的属性自动注入
spring框架根据某些规则可以给引用类型赋值
1.byname按名称注入:
java类中引用类型的属性名和spring容器中(配置文件)的id名称一样,且数据类型是一致的,这样的容器中的bean,spring能够赋值给引用类型
<bean id="myStudent" class="com.bjpowernode.ba04.Student" autowire="byName">
<constructor-arg name="name" value="欧洗给"/>
<constructor-arg name="age" value="22"/>
<!-- <constructor-arg name="mschool" ref="myxuexiao"/>-->
</bean>
<bean id="school" class="com.bjpowernode.ba04.School" >
<property name="name" value="清华大学"/>
<property name="address" value="北京海淀区"/>
</bean>
2.byType(按类型注入):
java类中引用类型的数据类型和spring容器中配置文件的class属性时同源关系,这样的bean能够赋值给引用类型
同源就是一类的意思:
1.java类中引用类型的数据类型和bean的class的值是一样的
2.java类中引用类型的数据类型和bean的class的值父子类关系的
3.java类中引用类型的数据类型和bean的class值时接口和实现类关系的
<bean id="myStudent" class="com.bjpowernode.ba04.Student" autowire="byType">
</bean>
2.4 注解的使用
1.使用注解的步骤:
1.加入maven的依赖 spring-context,在你加入spring-context的同时,间接加入spring-aop的依赖。使用注解必须使用spring-aop依赖
2.在类中加入spring的注解(多个不同功能的注解)
3.在spring的配置文件中,加入一个组件扫描器的标签,说明注解在你的项目中的位置
4.使用注解创建对象,创建对Applicationcontext
2.学习的注解:
@component
用来创建对象的,等于bean的功能
属性value是对象的名称也就是bean的id值,创建的对象在整个spring中就一个
位置在类的上面
@Repository (持久层)放在dao实现类,表示创建dao对象,dao对象是访问数据库的
@Service (用在业务层类的上面):放在service实现类上面,创建service,可以做事务处理
@Controller(用在控制器的上面):放在控制器类的上面,创建控制器对象,能够接收用户提交的参数,显示请求的处理结果
以上三个使用方法和component一样,但是还有额外功能,他们是给项目分层的
@Value
在定义的属性上直接对属性进行赋值
@Value(value = "张飞")
private String name;
@Value(value = "20")
private int age;
@Autowired
引用类型赋值 默认使用byType注入
1.在属性定义的上面,无需set方法,推荐使用
2.在set方法上面
byname自动注入:
@Autowired(required=true)建议使用
@Qualifier(“mySchool”)value=“bean的id”:表示使用指定名称的bean进行赋值
@Resource
来自jdk的注解,spring框架提供了对这个注解的功能支持,可以使用它给引用类型赋值,使用的也是byname,bytype默认是byname
1.在属性定义上,无需set,直接使用
2.在set上面
只使用byname方式需要添加name
name值为bean的id
3.AOP面向切面编程
1.动态代理
1.实现方式:
jdk动态代理:使用jdk的proxy,Method, InvocationHanderl创建代理对象
jdk代理必须要求目标类必须实现目标接口
cglib动态代理:第三方的工具库,创建代理对象,原理是继承。通过继承目标类,创建子类。子类就是代理对象。要求目标类布恩那个是final,方法也不能是final
2.动态代理的作用:
1.在实现目标类源代码不改变的情况下,增加功能
2.减少代码的重复
3.专注业务逻辑代码
4.解耦合
2.AOP
1.定义
aop(Aspect Orient programming):面向切面编程,基于动态代理的,可以使用jdk,cglib两种代理方式。aop就是动态代理的规范化,把规范化的实现步骤都定义好了,让开发人员用一种·统一的方式,就用动态代理。
什么时候使用aop技术
1.当你要给一个系统中存在的类修改功能,但是原有类的功能不完善,但是你还有源代码,使用aop就可以增加功能
2.你要给多个类,增加一个相同的功能,使用aop
3.给业务方法增加事务,日志输出
Aspect:切面就是给目标类添加的功能,就是切面。
orient: 面向
programming :编程
怎么理解面向切面编程:
1.需要在分析项目的功能是,找出切面
2.合理的安排切面的执行时间(在目标方法前,还是在目标方法后)
3.合理的安全切面执行的位置,在哪个类,哪个方法后增加功能
2.术语
- Aspect:切面,表示增强的功能,就是一堆代码完成某个功能,完成某个功能。非业务功能,常见的有日志,事务,统计信息,参数检查,权限认证
2)JoinPoint:连接点,连接业务方法和切面的位置。就某类中的业务方法而言
在切面方法中添加dosome(JoinPoint jp)
调用joinPoint中的方法可以获取切面方法的信息
3)Pointcut:切入点,指多个连接点方法的集合。多个方法
4)目标对象:给哪个类的方法增加功能,这个类就是目标对象
5)Advice:通知,表示切面功能执行的时间
一个切面三个关键的要素:
1.切面的功能代码,表示切面要干什么
2.切面的执行位置,使用pointcut表示切面执行的位置
3.切面的执行时间:在目标方法之前还是目标方法之后
3.实现
aop是一个规范,是动态代理的规范化,一个标准
aop技术实现框架:
1.spring:spring在内部实现类aop规范,能做aop工作。但项目中很少使用spring的aop实现,因为比较笨重
2.aspecJ:一个专门做aop的框架
切入点表达式:execution(访问权限 方法返回值 方法声明(参数) 异常类型)加粗可省略
任意公共方法
execution(public* *(…))
指定切入点为一set开始的方法
execution(* set*(…))
指定切入点为:在com.xyz.service类里任意返回值的任意方法
execution(* com.xyz.service..(…))
所用包下service子包下所有类中所有方法作为切入点
execution(* …service..*(…))
4.aspectj框架使用步骤
1.新建maven项目
2.加入依赖
1)spring依赖
2)aspecj依赖
3)junit单元测试
3.创建目标类:接口和他的实现类
要做的是给类中的方法增加功能
4.创建切面类:普通类
1)在类的上面加入@Apect
2)在类中定义方法,方法就是切面要执行的功能代码
方法的定义要求:
1.公共方法
2.无返回值
3.名称自定义
4.方法可以有参数也可以没有参数
在方法的上面加入aspecj中的通知注解,例如@Before@afterReturnning@Around
还需要指定切入点表达式
5.创建spring配置文件
声明对象,把对象交给容器统一管理,声明对象可以使用注解或xml配置文件
1.声明目标对象
2.声明切面类对象
3.声明aspectj框架中的自动代理生成器标签
自动代理生成器:用来完成代理对象的自动创建功能
6.创建测试类,
从spring容器中获取目标对象(实际上就是代理对象)。
通过代理执行方法,实现aop的功能增强。
7.通知注解介绍:
1.@Before:前置通知,在目标方法之前先执行切面功能
1.公共方法
2.无返回值
3.名称自定义
4.方法可以有参数也可以没有参数
2@afterReturning:后置通知,在目标方法之后执行切面功能
1.公共方法
2.无返回值
3.名称自定义
4.方法可以有参数也可以没有参数
3@Around:环绕通知:在目标前后都能增强功能,控制目标方法的访问,修改返回值
1.公共方法
2.有返回值,建议为object类型
3.名称自定义
4.方法必须有参数参数为ProceedingJoinPoint
4@AfterThrowing:异常通知,在目标方法抛出异常后执行的通知
1.public
2.没有返回值
3.方法名称自定义
4.方法可以有参数exception,还可以有Joinpoint
特点:1.在目标方法抛出异常时执行
2.可以做异常的监控程序,监控目标方法执行时是否有异常,如果有异常,可以发送邮件,短信进行通知
@after最终通知
特点:1.总是会执行2.在目标方法后执行
pointcut:定义和管理切入点,如果你的项目有多个切入点表达式时重复的,可以复用的可以使用@pointcut
在自定义方法时,此时这个方法就是切入点表达式的别名,其他通知value就可以使用别名代替表达式
8.代理的使用方式:
如果目标类有接口,框架使用jdk动态代理
如果目标类没有接口,默认使用cglib动态代理
有接口也可以强制使用cglib动态代理
在配置文件中加入<aop:aspectj-autoproxy proxy-target-class=“ture”>就可以告诉框架使用cglib代理
4.Spring和Mybatis的结合
1.实现步骤:
1.创建maven项目
2.加入maven依赖
3.创建实体类
4.创建dao接口和mapper文件
5.创建mybatis主配置文件
6.创建Service接口和实现类,属性是dao
7.创建spring的配置文件:声明mybatis的对象交给spring创建
1.数据源
2.SqlSessionFactory
3.Dao对象
4.声明自定义的service
8创建测试类,获取Service对象,通过Service调用dao完成数据库的访问
5.Spring事务处理
1.什么是事务:
事务是指一组sql语句的集合,集合中有多条sql语句,希望这些语句都能成功或都失败,这些sql语句的执行是一致的,作为一个整体执行。
2.什么时候使用事务:
涉及多个表或多个sql语句。需要这些语句都成功或都失败才能实现的功能
3:如何访问数据库
通常用jdbc访问数据库,还是mybatis怎么处理事务
jdbc访问数据库:Connection conn;conn.commit();conn.rollback()
mybatis访问数据库:Sqlsession.commit() SqlSession.rollback()
4.事务的处理方式有什么不足
1.不同的数据库范围跟技术,处理事务的对象,方法不同
需要了解不同数据库访问技术使用事务的原理
2.掌握多种数据库中事务的处理逻辑。什么时候提交事务,什么时候回顾事务
3处理事务的多种方法
5.怎么解决不足:
spring提供一种处理事务的统一模型,能使用统一步骤,方式完成多种不同数据库访问技术的事务处理
使用spring的事务处理机制:可以完成mybatis访问数据库的数据处理
使用spring的事务处理机制:可以完成hibernate访问数据库的数据处理
6.处理事务要怎么做,做什么
spring处理事务的模型,使用的步骤都是固定的。把事务使用的信息提供给spring就可以了
1:事务内部提交,回滚事务
使用的是事务管理器对象,代替你完成commit和rollback
事务管理器是一个接口和他众多实现类
接口PlatformTransactionManager,定义了事务重要方法commit,rollback
实现类:spring把每一种数据库访问技术对应的事务处理类都创建好了
mybaits访问数据库-spring创建好的是DataSourceTransactionManager
hibernate访问数据库-spring创建好的是HibernateTransactionManager
使用方法:你要告诉spring使用的是哪种数据库的访问计数,在配置文件中使用声明就可以了
2.说明需要事务的类型
1).隔离级别
定义了四个事务隔离级别常量()
这些常量均以ISOLATION_开头 即形如ISOLATION_XXX
DEFAULT:采用DB默认的事务隔离级别。MySql的默认为REPEATABLE_READ:Oracle默认为READ_COMMITED
READ_UNCOMMITED:读未提交。未解决任何并发问题
READ_COMMITED:读已提交。解决脏读,存在不可重复读与幻读。
REPEATTABLE_READ:可重复读。解决脏读,不可重复读,存在幻读
SERIALIZABLE:串行化。不存在并发问题
2).事务的超时时间
标识一个方法最长的执行时间,如果方法执行时超过了时间,事务就回滚。单位为秒,默认值-1.
3).事务的传播行为
控制业务方法是不是有事务,是什么样的事务
7个传播行为,表示你的业务方法调用时,事务在方法之间时如何使用的
PROPAGATION_REQUIRED
必须在事务内进行,没有事务spring会帮你创建事务
PROPAGATION_REQUIRES_NEW
总要新建一个事务,若当前存在事务,就将事务挂起,直到新事务执行完毕
PROPAGATION_SUPPORTS
可以在事务中执行,也可以不在事务中执行例如查询操作
以上三个需要掌握
PROPAGATION_MANDATORY
PROPAGATION_NESTED
PROPAGATION_NEVER
PROPAGATION_NOT_SUPPORTED
3.事务提交事务,回滚事务的时机
1.当你的业务方法,执行成功,没有异常抛出,当方法执行完毕,spring会在方法执行后提交事务,调用事务管理器commit
2.当你的业务方法抛出运行时异常,spring执行回滚,调用事务管理器rollback方法。运行时异常的定义:RuntimeException 和他的子类都是都是运行时异常,例如NullPointException,NumberFormatException
3.当你的业务方法抛出非运行时异常,主要是受查异常时提交事务。
受查异常:在你写代码中必须处理的异常。例如IOException,SQLException
总结spring的事务
1.管理事务的是事务管理器和他的实现类
2。spring的事务时统一类型
1)指定要使用的事务管理器实现类使用
2)指定哪些类,哪些方法需要加入事务的功能
3)指定方法的隔离级别,传播行为,超时
4.管理事务
4.1使用spring的注解管理事务
通过@Transactional注解方式,可将事务织入到相应的public方法中,实现事务管理。
@Transactional的所有可选属性如下所示
propagation:用于设置事务传播属性。该属性类型属于Propagation枚举,默认值为Propagation。REQUIRED
isolation:用于设置事务的隔离级别。该属性类型为Isolation枚举,默认值为Isolation.DEFAULT
readOnly:用于设置该方法对数据库的操作是否是只读的。该属性为boolean,默认值为false。都为查询操作时为true可以提高查询效率
timeout:用于设置本操作与数据库连接的超时时限。单位为秒,类型为int,默认值为-1.没有时限
rollbackFor:指定需要回滚的异常类。类型为class[],默认值为空数组。当然,若只有一个异常类时,可以不使用数组。
rollbackForClassName:指定需要回滚的异常类类名。类型为String[],默认值为空数组。当然,若只有一个异常类时,可以不使用数组
norollbackFor:指定不需要回滚的异常类。类型为class[],默认值为空数组。当然,若只有一个异常类,可以不使用数组。
使用@Transactional的步骤
1.需要声明事务管理器对象
2.开启事务注解驱动,告诉spring框架,使用注解的方式管理事务
使用aop机制
@Around
Object myAround(){
try{
buy(1001,10);
spring的事务管理.commit
}
catch(Exception e){
spring的事务管理.rollback();
}
}
4.2使用aspecj处理事务
实现步骤:
1添加依赖:
2.添加事务管理器:
3.声明方法需要事务类型(配置方法的事务属性(隔离级别,传播行为,超时))
3.配置aop