Spring
ioc控制反转
-
spring是轻量级开源框架,以Ioc和Aop为内核,它可以整合开源世界著名的第三方框架和类库,.
-
Spring的优势
(1) 方便解耦,简化开发
(2) AOP编程的支持
(3) 声明事物的支持
(4) 方便程序的测试
(5) 方便继承各种优秀框架
(6) 降低javaEE API的使用难度
(7) Java源码是经典的学习规范
-
在实际开发中应该做到,编译器不依赖,运行期才依赖
-
控制反转
(1) 作用:削减计算机程序的耦合
- 基于xml的IOC细节的掌握
(1) beanFactory与applicationContext的区别
① applicationContext:一读取配置文件默认情况下就会创建对象
② beanFactory:什么时候用什么时候进行创建
(2) Bean标签中的细节
① id
② Class:在默认的情况下是调用无参的构造方法;
③ Scope:指定对象的作用范围
-
Singleton:单例模式:在默认的情况下是单例模式,applicationContext在创建的时候创建的是单例模式对象,多例模式的对象是在获取的时候创建的;
-
Prototype:多例模式
-
Requset:
-
Session:
-
Global session :
④ Init-method:初始化的方法
⑤ Destory-method:指定类中的销毁方法
(3) Bean的作用那个范围和声明周期
① Scope=”singleton”
-
一个应用只有一个对象的实例,它的作用范围是整个应用
-
生命周期
a. 对象出生:当应用被加载,创建容器,对象就被创建了
b. 对象活着:只要容器在对象就一直活着
c. 对象死亡:当应用卸载,销毁容器时;对象就被销毁了
② 多例对象:scope=”prototype”,
-
每当访问对象时,都会重新创建对象的实例
-
生命周期
a. 对象出生:当使用对象时,创建新的对象实例
b. 对象活着:只要对象在是使用中,就一直活着
c. 对象销毁:对象长时间不用时,就被java的垃圾回收器回收了;
(4) 实例化对象的3种方式:
①
<bean id= “” class=””>
②
<bean id= “” class = “ 静态工厂的全类名” factory-method=”静态方法的名字”>:静态工厂的创建方式
- 需要注意的是:需要创建一个静态工厂来创建实例
③
<bean id= “ ” class = “实例工厂的全类名”> <bean id=”” factory-bean=”实例工厂对象的id” factory-method=”实例工厂中的方法”>
(5) 依赖注入是spring框架核心IOC的具体体现
① 构造函数的注入
1) <constructor-arg name=”” value></construction-arg>
2) <constructor-arg index=”” value></construction-arg>
3) <constructor-arg type=”” value></construction-arg>
4) <constructor-arg name=”” ref=”a”></construction-arg>
a. <bean id=”a” class=””>
② Set方式注入
-
方法中必须要有空参的构造方式
-
Value中只能存放简单的数据类型还有string
a.
<property name=”” value=””>
b. 当遇到引用类型的时候
a)
<property name=”” ref=”a”>
i.
<bean id=”a” class=””>
③ P空间注入数据
-
在命名空间出添加如下的字段:xmlns:p=“http://www.springframework.org/schema/p”
<bean id=”” class=”” p:name=”” p:age=”” p:birthday-ref=”a”>
a.
<bean id=”a” class=””>
④ 注入集合属性:
- List集合
a.
<property name=””>
<list>
<value>
..............只能写一个属性
<value>
<!--但是value可以写多个-->
<list>
</property>
- set集合 数组与上述的相同
⑤ Map集合和properties集合
- Map集合
<property name="myProps">
<map>
<entry key="testA" value="aaa"></entry>
<entry key="testB">
<value>bbb</value>
</entry>
</map>
</property>
- properties集合
<property name="myMap">
<props>
<prop key="testA">aaa</prop>
<prop key="testB">bbb</prop>
</props>
</property>
- 单例模式
\1. 什么是单例模式
就是只能创建一个对象
\2. 实现单例模式
1) 屏蔽构造方法
2) 提供一个静态的方法,返回该类的对象
方法应该判断对象是否是惟一的
//懒汉式–单例模式
private static BeanFactory beanFactory;
public static BeanFactory newInstance(){
//在返回之前做一个判断,判断是否为null,如果为null,则创建,不为null,直接返回
if(beanFactory == null){
beanFactory = new BeanFactory();
}
return beanFactory;
}
// 饿汉式-单例模式
//提前创建对象
private static BeanFactory beanFactory = new BeanFactory();
//提供一个静态的方法,创建对象
public static BeanFactory getInstance(){
return beanFactory;
}
- 常用的注解:
(1) 在配置文件中扫描包
①
<context:component-scan basepackage=”包名” >
(2) Component 注解在类上,三层都可以
① 注意事项:
- 如果在实现类中有多个相同的实现类即.class文件相同,如果不配置别名,那么就会出现找不到类的异常,所以在有多个实现类的时候,需要进行配置别名
(3) 针对component的衍生类
① Controller 用于表现层的
② Service 用于业务层
③ Repository 用于持久层的
④ 注意事项:
-
上述的三种作用是相同的,只是提供了更加明确的语义化
-
如果属性中有且仅有一个属性需要赋值时,且名称是value,value在赋值中是可以不写的
(4) @autowired
① 作用:自动的按照类型进行注入,如果实现类的类型有多个,那么,就会匹配不到类型,这是就需要用到@qualifier提供名字
② @qualifier 是在自动注入的基础之上,在按照bean的id进行注入的,当它在给字段注入时不能单独使用,必须与@autowired一块使用,否则没有意义.但是当给方法参数注入时,就可以独立的使用;
③ @resource 默认是按照bean的名字进行注入的,其次才按照类型进行注入;
- Name属性:添加对应实现类的id
(5) @Value
① 注入基本的数据类型和string类型
② 主要用于指定值
(6) @Scope 使用与指定bean的作用范围
① 主要的取值
-
Singleton 单例模式
-
Prototype 多例模式
-
Request
-
Session
-
globalsession
(7) 与生命周期相关的注解
① @postcontract 用于指定初始化的方法
② @predestroy 用于指定销毁的方法
(8) 在使用注解是需要告知spring框架读取配置文件,扫描注解:
①
- 利用全注解进行开发
(1) @configuration 用于指定配置类
① value:用于指定配置类的字节码
(2) @componentscan 用于扫描包
① 其中的属性basepackage与注解中的一样,同时它是value属性,所以属性名可以不写
(3) @bean 这个注解只能写在方法上,标明用此方法创建一个对象,并且放入spring容器中;
① Name属性,为bean创建的方法给出一个名字,即bean的id
(4) @propertysource 为配置类引入文件
① 属性:classpath:+名字
(5) @import 用于导入其他的配置文件(类)
① 属性:value[] 为数组 导入外面配置文件的class对象
- 当通过全注解进行开发的时候在测试类中则变为:
New annotationconfigapplicationContext(配置文件的class文件);
- spring整合Junit
(1) 需要导入spring的test坐标
(2) Junit需要使用4.12以上的版本
(3) @runwith(SpringJUnit4ClassRunner.class)
(4) @contextcongfiguration(locations={“classpath:+文件名”})
① 同时也是可以写类名
aop:面向切面编程
- aop:面向切面的编程
(1) 通过预编译和运行时期动态代理实现程序功能的统一维护的一种技术.
(2) 将重复的代码提取出来,在需要执行的时候,使用动态代理的技术,在不修改源码的基础上进行增强;
(3) aop的作用和优势
① 作用:在程序运行期间在不修改代码的基础上对已有方法进行增强
② 优势:
-
减少重复代码
-
提高开发效率
-
维护方便
-
aop实现的方式是动态代理技术
-
动态代理技术
(1) 字节码随用随创建,随用随加载,静态代理是字节码以上来就创建好了,并且完成加载,它与静态代理的区别也在于此。因为静态代理是字节码一上来就创建好,并完成加载。装饰者模式就是静态代理的一种体现。
- 动态代理的两种方式
(1) Jdk动态代理:基于接口的动态代理
① Jdk官方提供的prox类
② 要求:被代理的类必须实现至少一个接口
③ 创建代理对象的方法:proxy.newproxyinstance()
④ 参数:类加载器,被代理类的接口,实现invovationhandler()接口
⑤ 实现类中重写方法的返回值是加强方法的返回值
(2) Cglib动态代理:基于子类的动态代理
① 第三方提供的cglib
② 被代理的类不能被final修饰(最终类)
③ 创建代理对象的方法:enhancer.creat
④ 参数:被代理对象的字节码文件,实现methodinterceptor()
⑤ 实现类中重写方法的返回值是加强方法的返回值
- aop的相关细节
(1) Aop的相关术语
① Jointpoint 连接点,被拦截到的点,在spring中指的是拦截到的方法,因为spring只支持方法类型的连接点
② Pointcut 切入点 对哪些joinpoint进行拦截,就是通知joinpoint对哪些方法进行拦截
③ Advice 增强/通知 拦截到方法之后所做的事情就是通知,通知有以下五种类型:
- 前置通知 before
<aop:before method=”方法名” pointcut=”excutor()”>
<!--下面的几种通知方式类似-->
-
后置通知 after-returning
-
异常通知 after-throwing
-
最终通知 after
-
环绕通知 around
④ Introduction 引介是一种特殊的通知在不修改类码的前提下,可以在运行期为类动态的添加一些方法或者filed
⑤ Target 目标对象 代理的目标对象
⑥ Weaving 是值把增强应用到目标对象来创建代理对象的过程
- Spring采用的是动态代理织入,而apsectJ采用的是编译器织入和类装载期织入
⑦ Proxy 一个了被织入增强后,就产生了一个结果代理类
⑧ Aspect 切面 是切入点和通知的结合
(2) 在spring中框架会根据目标类是否实现了接口来决定采用哪种的动态代理方式
(3) Aopxml文件的配置
① aop:config用于声明开始aop的位置
②
<aop:aspect id=”切面的唯一表示符” ref=”切面类名”>
③
<aop:pointcut: id=”” expression=”executio()”>
④
<aop:(环绕类型) method=”方法名” pointcut-ref=”pointcut的id”>
- 半注解进行开发
(1) 需要在xml文档中对spring注解aop的支持
①
(2) 将通知类上注解为@aspect表示其为一个切面
(3) @before(execution())前置通知
(4) @afterreturning 后置通知
(5) @afterthrowing 异常通知
(6) @after 最终通知
注意:当使用上述的注解在日志文件中的时候,spring在程序中找不到执行的顺序,所以,如果使用日志类进行通知,建议使用@around进行通知
(7) @around 环绕通知
(8) @pointcut(execution())
① private void pt1() {}
- 不适用xml注释:
(1) 则需要在配置文件类上加上注释@enableaspectJautoproxy
- JdbcTemPlate
(1) 引入外部文件的在xml中的配置:
①
<context:property-placeholder location=”classpath:”>
- jdbcTemplate两种使用方式
使用第一种方式:
(1) 在jdbcTemplate中存在有datasource的set方法所以可以使用,同时也是可以使用构造方法的形式来进行配置.
(2) Jdbctemplate的增删改查
① 需要常见一个mapper类来实现 实现 rowmapper接口,然后重写里面的方法;
② 里面常用的方法:
-
Query
-
查询一个的时候,使用queryforobject
使用第二中种方式:
(1) 继承jdbcdaosupport类里面有**private **JdbcTemplate jdbcTemplate
① 所以可以直接用this.进行调用,在继承的jdbcdaosupport中存在有DataSource的set方法,所以可以利用xml进行注入,
- 注意:使用这种继承的方法只能使用xml声明的方式进行开发,而第一种适合所有的配置方式
- spring中的事物控制:导入txjar包
(1) 事物是出于业务层的
(2) Spring的事物控制都是基于aop的,它既可以使用编程的方式进行实现,也可以使用配置的方式进行实现;
- 事务管理器的接口:platformtransactionmanager
(1) Gettransaction(transactiondefinition ds) 查看事务的状态
(2) Commit(transactionstatus status)提交事务
(3) Rollback(transactionstatus status) 回滚事务
- 真正管理事务的的对象
(1) DataSourcetransactionmanager 使用springjdbc或者mybatis进行持久化数据使用
(2) Hibernatetransactionmanager使用hibernate版进行持久化数据使用
- 事务的隔离级别
(1) Defalut默认级别
(2) Read-uncommit可以读取未提交的数据
(3) Reda-commit只能读取已经提交的数据,解决脏读的问题(oracle的默认级别)
(4) Repeatable-read是否读取其他事务提交修改的数据,解决不可重复读的问题(mysql的默认级别)
(5) Serializable:是否读取其他事务提交添加后的数据:结局幻读的问题
① 注意:等级越高,效率越低
- 事务的传播行为
(1) REQUIRED:如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。一般的选择(默认值)
(2) SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行(没有事务)
(3) Mandatory:使用当前事务,如果当前没有事务,就抛出异常
(4) REQUERS_NEW:新建事务,如果当前在事务中,把当前事务挂起。
(5) NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
(6) NEVER:以非事务方式运行,如果当前存在事务,抛出异常
(7) NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行 REQUIRED 类似的操作。
-
超时时间:默认是-1代表的是没有超时限制,如果有,以秒为单位进行设置
-
只读事务,建议查询的时候使用只读操作
-
Xml中声明事务控制步骤:
(1) 配置事务管理器
①
<bean id=”transactionmanager” class=”DataSourcetransactionmanager”>
<!--因为需要事务的控制,所以需要connection,而connection在datasource中所以需要数据源的配置-->
<property name=”datasource” ref=”datasource”>
</bean>
(2) 配置事务的通知引用事务管理器
①
<tx:advice id=”txAdvicer” transaction-manager=”transactionmanager” >
</tx:advice>
(3) 配置事务的属性,在通知的标签里
<tx:Attributes>
<tx:method name=”需要过滤方法的名字概写*” propagation="SUPPORTS" isolation="DEFAULT" read- only="true">
</tx:attribute>
(4) 配置aop切入点的表达式
<aop:config>
<aop:pointcut id=”pointcut” expression=”execution()”>
</aop:config>
(5) 配置切入点表达式和事务通知的对应关系
①
<aop:advisor advice-ref=”txAdvice” pointcut-ref=”pointcut”><aop:advisor>
-
完整版的xml进行配置:
<?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" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" 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 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <context:component-scan base-package="com.itheima"></context:component-scan> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver"></property> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/spring_day03"></property> <property name="user" value="root"></property> <property name="password" value="root"></property> </bean> <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl"> <property name="dataSource" ref="dataSource"></property> </bean> <!--创建事务管理器--> <!--自己写的再次声明id是随意写的,作为唯一标识符而已--> <!--下面的本就是为了事务进行的事物的管理器 所以需要春如DataSource,为了得到connection --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!--事物的通知增强,transaction-manager:指定事物管理器,即上面事物管理器的id--> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="save*" isolation="DEFAULT" read-only="false" propagation="REQUIRED"/> <tx:method name="del*" read-only="false" isolation="DEFAULT" propagation="REQUIRED"/> <tx:method name="update*" read-only="false" propagation="REQUIRED" isolation="DEFAULT"/> <tx:method name="transfer*" read-only="false" isolation="DEFAULT" propagation="REQUIRED"/> <tx:method name="*" read-only="true" isolation="DEFAULT" propagation="SUPPORTS"/> </tx:attributes> </tx:advice> <aop:config> <!--拦截作用--> <aop:pointcut id="pointcut" expression="execution(* com.itheima.service..*.*(..))"></aop:pointcut> <!--拦截到方法,然后通知事物开始执行事物--> <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"></aop:advisor> </aop:config> </beans>
-
注解开发步骤
(1) 配置事务管理器并注入数据源
(2) 在业务层使用@transactional(readonly=””),里面的属性的填写与配置文件相同
① 该注解的属性和 xml 中的属性含义一致。该注解可以出现在接口上,类上和方法上。
② 出现接口上,表示该接口的所有实现类都有事务支持。
③ 出现在类上,表示类中所有方法有事务支持
④ 出现在方法上,表示方法有事务支持。
⑤ 以上三个位置的优先级:方法>类>接口
(3) 在配置文件中开启spring对注解事务的支持
<tx:annotation-driven transaction-manager=”transactionManager”>
- 不适用xml方式配置
(1) 在配置类上需要添加@enabletransactionmanager标签