spring学习笔记
2021-07-06 14:29:31 0 举报
AI智能生成
spring学习笔记
作者其他创作
大纲/内容
Spring
架构演变
单一应用架构(数据访问框架ORM是关键)
垂直应用架构(MVC框架是关键)
分布式服务架构(分布式框架RPC是关键)
流动计算架构(用于提高机器利用率的资源调度和治理中心SOA是关键)
框架演变
JSP + Servlet(Serve Applet)+ JavaBean
MVC三层架构
EJB->过多的接口和依赖,侵入性强
Struts1/Struts2 + Spring + Hibernate
Spring + SpringMVC + Mybatis
SpringBoot->约定大于配置
Spring生态
SpringBoot
SpringCloud
中文文档
github.com->spring-docs
IOC(Inversion of Control)
IOC思想
1.IOC容器控制依赖的对象,对于程序员来说,由之前的主动创建依赖对象到现在的被动接收创建好的依赖对象。
2.IOC是思想,DI是具体实现。
控制反转(IOC):就是应用本身不负责依赖对象的创建和维护,依赖对象的创建及维护是由外部容器负责的,这样控制权就由应用转移到了外部容器,即控制权的转移就是控制反转。
依赖注入(DI):在程序运行期间,由外部容器动态地将依赖对象注入到组件中。主要通过构造函数或者setter来具体实现。
3.IOC容器的解耦作用
IOC容器初始化过程
第一个过程是Resource资源定位。这个Resouce指的是BeanDefinition的资源定位。这个过程就是容器找数据的过程,就像水桶装水需要先找到水一样。第二个过程是BeanDefinition的载入过程。这个载入过程是把用户定义好的Bean表示成Ioc容器内部的数据结构,而这个容器内部的数据结构就是BeanDefition。第三个过程是向IOC容器注册这些BeanDefinition的过程,这个过程就是将前面的BeanDefition保存到HashMap中的过程。在源码中表现为:refresh()方法中的obtainFreshBeanFactory()方法创建BeanFactory以及读取xml文件信息并将每个bean的定义注册为BeanDefinaton后放入一个HashMap中最后赋值给DefaultListableBeanFactory对象
bean的生命周期
IOC容器初始换完成后,当容器启动后就会实例化bean,此时开始了bean的生命周期
注意点
ApplicationContext就是IOC容器的接口,可以通过此对象获取容器中创建的对象
ClassPathXmlApplicationContext
FileSystemXmlApplicationContext
对象在Spring容器中默认是在容器创建完成的时候就已经创建完成,不是需要用的时候才创建,此种情况满足的是单例模式
对象在IOC容器中存储的时候都是单例的,如果需要多例需要修改属性
spring对象的获取(创建方式)
2.根据bean的类型来获取对象,注意:当通过类型进行获取的时候,如果存在两个相同类型对象,将无法正常获取。Person person = context.getBean(Person.class);<bean id="person" class="com.fan.bean.Person"></bean>
3.利用工厂方法创建bean
静态工厂:类名.静态方法()
public class PersonStaticFactory { public static Person getInstance(String name){ Person person = new Person(); person.setId(1); person.setName(name); person.setAge(11); return person; }}<bean id="person10" class="com.fan.factory.PersonStaticFactory" factory-method="getInstance"> <constructor-arg value="zhangsan"></constructor-arg> </bean>
实例工厂:先创建工厂实例,然后调用工厂实例的方法 factory-bean:表示具体工厂类的实例 factory-method:表示具体工厂实例的方法
public class PersonInstanceFactory { public Person getInstance(String name){ Person person = new Person(); person.setId(2); person.setName(name); person.setAge(22); return person; }}<!--先创建工厂实例--><bean id="instanceFactory" class="com.fan.factory.PersonInstanceFactory"></bean><!--再通过实例调用工厂方法--> <bean id="person11" class="com.fan.bean.Person" factory-bean="instanceFactory" factory-method="getInstance"> <constructor-arg value="lisi"></constructor-arg> </bean>
4.通过FactoryBean创建对象
FactoryBean是Spring规定的一个接口,对于FactoryBean接口的实现类,Spring都会将其作为一个工厂,但是在ioc容器启动的时候不会创建实例,只有在使用的时候才会创建对象。此方式是spring创建bean方式的一种补充,用户可以按照需求创建对象,创建的对象交由spring IOC容器来进行管理,无论是否是单例,都是在用到的时候才会创建该对象,不用该对象不会创建。使用方法:1、实现FactoryBean接口2、将实现类交给IOC容器去管理
public class MyFactoryBean implements FactoryBean<Person> { /* * 返回获取的bean * */ public Person getObject() throws Exception { Person person = new Person(); person.setId(3); person.setName("王五"); return person; } /* * 获取返回bean的类型 * */ public Class<?> getObjectType() { return Person.class; } /* * 判断当前bean是否是单例的 * */ public boolean isSingleton() { return false; }} <bean id="myFactoryBean" class="com.fan.factory.MyFactoryBean"></bean>
给对象赋值
1.通过property来给属性赋值,name的名称取决于set方法后面的参数首字符小写的名称。然后通过实体类的setter方法实现赋值
配置文件中:<bean id="person" class="com.fan.bean.Person" > <property name="id" value="1"></property> <property name="name" value="zhangsan"></property> </bean>实体类中:public void setId(int id) { this.id = id; }public void setName(String name) { this.name = name; }
2.过构造器来给属性赋值,name的名称由构造方法的参数列表来决定
name:表示参数列表的名称value:表示实际的具体值type:表示值的类型index:表示值的下标,从0开始
当通过构造器方法赋值的时候,name属性可以省略不写,但要注意value的赋值顺序要和构造方法参数列表一致
<constructor-arg value="2"></constructor-arg>
可以加index来保证顺序的正确
<constructor-arg value="2" index="0"></constructor-arg>
当有多个相同参数个数的构造方法存在的时候,默认情况下是覆盖的过程,后面的构造方法会覆盖前面的构造方法,如果非要赋值给另外一个构造方法的话,,可以使用type参数来指定类型
<constructor-arg value="22" type="java.lang.Integer"></constructor-arg>
3.使用p命名空间给属性赋值
xmlns:p="http://www.springframework.org/schema/p"<bean id="person6" class="com.fan.bean.Person" p:id="5" p:name="wangwu" p:age="25" p:gender="女"> </bean>
xmlns: xml namespace
xsi: xml schema instance
4.给复杂类型赋值
<!--给set属性赋值--> <property name="sets"> <set> <value>zhangsan</value> <value>zhangsan</value> <value>wangwu</value> </set> </property>
<!--给map赋值--> <property name="maps"> <map> <entry key="a" value="aaa"></entry> <entry key="address" value-ref="address"></entry> <entry key="address2"> <bean class="com.fan.bean.Address"> <property name="province" value="广东省"></property> </bean> </entry> <entry> <key> <value>hehe</value> </key> <value>haha</value> </entry> <entry key="list"> <list> <value>11</value> <value>22</value> </list> </entry> </map> </property>
<!--给properties赋值--> <property name="properties"> <props> <prop key="111">aaa</prop> <prop key="222">bbb</prop> </props> </property>
5.可以通过parent属性来获取父bean中的某些属性值
<!--bean之间的继承关系. 可以使用abstract标签定义抽象bean,为true时无法进行实例化--> <bean id="parent" class="com.fan.bean.Person" abstract="false"> <property name="id" value="1"></property> <property name="name" value="zhangsan"></property> <property name="age" value="20"></property> <property name="gender" value="男"></property> </bean> <!--可以通过parent属性来获取父bean中的某些属性值--> <bean id="son" class="com.fan.bean.Person" parent="parent"> <property name="name" value="haha"></property> </bean>
bean的所用域
通过scope属性可以指定当前bean的作用域 singleton:单例模式,从IOC容器中获取的都是同一个对象,默认的作用域 prototype:多例模式,从IOC容器中获取的对象每次都是新创建 注意: 如果是singleton作用域的话,每次在创建IOC容器完成之前此对象已经创建完成 如果是prototype作用域的话,每次是在需要用到此对象的时候才会创建 在spring4.x的版本中还包含另外两种作用域: request:每次发送请求都会有一个新的对象 session:每一次会话都会有一个新的对象<bean id="person9" class="com.fan.bean.Person" scope="prototype"></bean>
初始化和销毁方法
spring容器在创建对象的时候可以指定具体的初始化和销毁方法 init-method:在对象创建完成之后会调用初始化方法 destory-method:在容器关闭的时候会调用销毁方法初始化和销毁的方法跟scope属性也是相关的 如果是singleton的话,初始化和销毁的方法都存在 如果是prototype的话,初始化方法会调用,但是销毁的方法不会调用
//实体类中定义普通的方法public void init(){ //编写N行逻辑代码完成初始化功能 System.out.println("person对象初始化完成"); } public void destory(){ System.out.println("person对象被销毁"); } <bean id="person12" class="com.fan.bean.Person" init-method="init" destroy-method="destory"></bean>
bean对象的增强处理
BeanPostProcessor使用步骤:1、实现BeanPostProcessor接口并重写其中的方法2、交给IOC容器管理
自动装配
创建第三方bean对象
引入外部配置文件
SpEL表达式语言的使用
BeanFactory和FactoryBean的区别
BeanFactory接口和ApplicationContext接口
相同:- Spring提供了两种不同的IOC 容器,一个是BeanFactory,另外一个是ApplicationContext,它们都是Java interface,ApplicationContext继承于BeanFactory(ApplicationContext继承ListableBeanFactory。- 它们都可以用来配置XML属性,也支持属性的自动注入。- 而ListableBeanFactory继承BeanFactory),BeanFactory 和 ApplicationContext 都提供了一种方式,使用getBean("bean name")获取bean。不同:- 当你调用getBean()方法时,BeanFactory仅实例化bean,而ApplicationContext 在启动容器的时候实例化单例bean,不会等待调用getBean()方法时再实例化。- BeanFactory不支持国际化,即i18n,但ApplicationContext提供了对它的支持。- BeanFactory与ApplicationContext之间的另一个区别是能够将事件发布到注册为监听器的bean。- BeanFactory 的一个核心实现是XMLBeanFactory 而ApplicationContext 的一个核心实现是ClassPathXmlApplicationContext,Web容器的环境我们使用WebApplicationContext并且增加了getServletContext 方法。- 如果使用自动注入并使用BeanFactory,则需要使用API注册AutoWiredBeanPostProcessor,如果使用ApplicationContext,则可以使用XML进行配置。- 简而言之,BeanFactory提供基本的IOC和DI功能,而ApplicationContext提供高级功能,BeanFactory可用于测试和非生产使用,但ApplicationContext是功能更丰富的容器实现,应该优于BeanFactory
AOP(Aspect-oriented Programming)面向切面编程
AOP定义
面向切面编程(AOP)是对面向对象编程(OOP)的一种补充,AOP提供了一种不一样的编程思想,这个不一样体现在:OOP更多关注的是类,而AOP关注的是切面,并且切面在AOP中是模块化的,如事务管理、日志管理等都可以作为切面来在需要的地方提供相应的服务。同时,AOP也是对IOC的一种增强,但IOC和AOP之间是独立的。其中,AOP最重要的两个思想点是:1、 提供声明式企业服务。此类服务中最重要的是声明式事务管理。AOP出现之前,对于事务管理我们都是通过编程式的事务管理,比如手动提交、回滚等。而AOP的事务管理是声明式的,可以简单的通过注解来实现,大大简化了对于事务的操作。2、用户可以自定义切面。这意味着你可以在程序运行期间织入自己想要实现的一些功能。
AOP原理
Spring AOP使用的动态代理,所谓的动态代理就是说AOP框架不会去修改字节码,而是在内存中临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理。JDK动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口。JDK动态代理的核心是InvocationHandler接口和Proxy类。如果目标类没有实现接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成某个类的子类,注意,CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。由于cglib会动态生成某个类的子类,当生成的类过多的时候占用内存过大可能会造成OOM,因为MataSpace默认为21M,所以需要设置其大小,一般设置为230M左右。项目中一般要设置的参数为:线程、堆初始大小以及堆最大大小、元空间初始大小以及元空间最大大小。
AOP术语
AOP中的术语:Aspect:切面。对关注点的模块化,所谓关注点可以理解为应用程序中公共部分代码逻辑,比如对事物的管理、日志的管理等代码逻辑可以作为一个模块来供其他代码中使用,该模块在AOP中通常称为切面。具体实现方式:xml配置或者注解。xml的方式在随后的代码中讨论,注解的方式通俗的来说就是在普通类上面加一个@Aspect注解。Join point:连接点。程序执行期间的一个点,如方法执行或异常处理期间的一个点。在Spring AOP中,连接点总是表示方法执行。连接点正是通知方法执行的时机。advice:通知。用来定义在切面的连接点上采取的操作(某一个方法)。通知类型有五种,以注解的方式来看包括:@Before、@After、@AfterReturning、@AfterThrowing、@AroundPointcut:切入点。从注解的方式来看,切入点是用来定义连接点的一种表达式,通知就是执行在切入点定义好的连接点之上的。用切入点来定义连接点可以在通知中更简洁的引入,当然也可以不用切点来定义连接点,连接点可以直接在通知中进行定义。Introduction: 引入。引入其他方法或字段。Spring AOP允许向任何被建议的对象引入新的接口(以及相应的实现)。例如,可以让bean实现一个IsModified接口,以简化缓存。(在AspectJ社区中,引入称为类型间声明。)Target object:目标对象。被一个或多个切面通知的对象。也称为被通知的对象。因为Spring AOP是通过使用运行时代理实现的,所以这个对象始终是一个代理对象。AOP proxy:AOP框架为了实现切面契约(通知方法的执行等等)而创建的对象。在Spring框架中,AOP代理是JDK动态代理或CGLIB代理。Weaving:织入。将切面与其他应用程序类型或对象链接以此来创建一个通知对象。这可以在编译时(例如使用AspectJ编译器)、加载时或运行时完成。与其他纯Java AOP框架一样,Spring AOP在运行时完成织入。
AOP使用
AOP注解的方式:需要的包可以通过maven导入:spring-context(maven会自动下载该包的相关依赖,比如spring-aop等)、cglib、aspectjrt、aopalliance、spring-aspects。
applicationContext.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: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/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!--开启包的扫描--> <context:component-scan base-package="com.fan"></context:component-scan> <!--开启AOP的注解功能--> <aop:aspectj-autoproxy></aop:aspectj-autoproxy></beans>
AOP的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: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/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <bean id="logUtil" class="com.fan.util.LogUtil"></bean> <bean id="myCalculator" class="com.fan.service.MyCalculator"></bean> <!--配置aop--> <aop:config> <!--定义全局的pointcut--><!-- <aop:pointcut id="globalPointCut" expression="execution( Integer com.fan.service.MyCalculator.*(..))"/>--> <!--声明切面--> <aop:aspect ref="logUtil"> <!--将通用的表达式抽取出来--> <aop:pointcut id="myPointCut" expression="execution( Integer com.fan.service.MyCalculator.*(..))"/> <!--定义切面中的通知方法在切入点所定义的连接点方法上使用--> <aop:before method="start" pointcut-ref="myPointCut"></aop:before> <aop:after method="logFinally" pointcut-ref="myPointCut"></aop:after> <aop:after-returning method="stop" pointcut-ref="myPointCut" returning="result"></aop:after-returning> <aop:after-throwing method="logException" pointcut-ref="myPointCut" throwing="e"></aop:after-throwing> <aop:around method="around" pointcut-ref="myPointCut"></aop:around> </aop:aspect> <aop:aspect ref="securityUtil"> <aop:before method="start" pointcut-ref="myPointCut"></aop:before> <aop:after method="logFinally" pointcut-ref="myPointCut"></aop:after> <aop:after-returning method="stop" pointcut-ref="myPointCut" returning="result"></aop:after-returning> <aop:after-throwing method="logException" pointcut-ref="myPointCut" throwing="e"></aop:after-throwing> <aop:around method="around" pointcut-ref="myPointCut"></aop:around> </aop:aspect> </aop:config></beans>
AOP对事务的管理
AOP基于注解的声明式事务
用到的jar包:spring-context、cglib、aspectjrt、aopalliance、spring-aspects、druid、mysql-connector-java、spring-jdbc
applicationContext.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" 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"> <context:component-scan base-package="com.fan"></context:component-scan>\t<!--加载数据库配置文件--> <context:property-placeholder location="classpath:db.properties"></context:property-placeholder> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="username" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> <property name="url" value="${jdbc.url}"></property> <property name="driverClassName" value="${jdbc.driverName}"></property> </bean> <!--JdbcTemplate相当于增删改查模板--> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> <!--配置事务管理器的bean对象--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!--开启基于注解的事务管理器的配置--> <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven></beans>
以上事务类中需要注意: * @Transactional(propagation = Propagation.XXX)注解中的值: propagation:传播特性:表示不同的事务之间执行的关系,调用事务方法的事务方法与当前事务方法在不同的类中时才有事务传播特性,如果是在同一个类中,则被认为是同一个事务,不再具备AOP的事务传播特性。 spring的事务传播行为共有7种:(以下当前方法是指被事务注解Transactional()标记的方法) 1、REQUIRED:如果有事务在运行,当前的方法(被调用的事务方法)就在这个事务内运行,否则就启动一个新的事务,并在自己的事务内运行 如果当前方法有异常,即使在调用当前方法的方法(事务方法)中将当前方法的异常进行try catch,那么调用当前方法的方法中的其他代码仍然会进行回滚。 如果调用当前方法的事务方法中有异常或者调用当前方法的事务方法中调用的其他方法有异常,那么当前方法会进行回滚。 总结:REQUIRED事务方法依赖于外部事务方法,无论是当前事务方法还是调用当前事务方法的事务方法,只要任意一个事务方法中有异常,那么全部事务方法都将进行回滚。 2、REQUIRES_NEW:当前的方法启动新事务(这种事务是独立的,与调用当前方法的方法是否有事务无关),并在它自己的事务内运行,如果有事务正在运行,应该将他挂起(暂停)。 如果当前方法有异常,并且在调用当前方法的方法(事务方法)中将当前方法的异常进行try catch捕获处理,那么调用当前方法的方法中的其他代码不会进行回滚,而只对当前方法的代码进行回滚。也就是说,REQUIRES_NEW启动一个独立的新事务,该事务不会影响其他事务并且也不会受其他事务的影响。 如果调用当前方法的方法中有异常,那么当前方法不会进行回滚,因为当前方法是一个独立的新事务且没有异常,无需进行回滚。 总结:REQUIRES_NEW事务方法不依赖于外部事务方法,只有当前事务方法中有异常才会进行回滚。 3、SUPPORTS:如果有事务在运行,当前的方法就在这个事务内运行,否则它不运行在事务中 4、NOT_SUPPORTED:当前的方法不应该运行在事务中,如果有运行的事务,将他挂起,直到当前方法执行完毕 5、NEVER:当前的方法不应该运行在事务中,如果有运行的事务,就抛出异常(即当前方法不会正常执行) 6、MANDATORY:当前的方法必须运行在事务内,如果没有正在运行的事务,就抛出异常(即当前方法不会正常执行) 7、NESTED:如果有事务在运行,当前的方法就应该在这个事务的嵌套事务(被调用的子事务方法,包括当前方法)内运行,否则,就启动一个新的事务,并在它自己的事务内运行. 如果当前方法有异常,并且在调用当前方法的方法(事务方法)中将当前方法的异常进行try catch捕获处理,那么调用当前方法的方法中的其他事务方法代码不会进行回滚,而只对当前方法的代码进行回滚,这与REQUIRES_NEW相同。 如果调用当前方法的方法中有异常且没有进行try catch异常捕获处理,那么全部事务方法将进行回滚,这与REQUIRES_NEW刚好相反。 也就是说NESTED事务方法除了于自身有关外与调用当前方法的事务方法也是有关系的,只要调用当前方法的事务方法中有异常或者调用当前方法的事务方法中调用的其他方法有异常,那么当前方法就会进行回滚。 总结:NESTED事务方法有异常,那么NESTED事务方法将进行回滚。调用NESTED事务方法的事务方法有异常,那么全部事务方法将进行回滚。 * timeout:超时时间,单位为秒,超过该时间就会进行回滚 * readonly:只读事务:如果配置了只读事务,那么在事务运行期间,不允许对数据进行修改,否则抛出异常 * 设置哪些异常发生时事务不进行回滚:两者除了参数形式不同外,功能相同 noRollBackFor: 如:noRollbackFor = {ArithmeticException.class} noRollBackForClassName: 如:noRollbackForClassName = {"java.lang.ArithmeticException"} * 设置哪些异常发生时进行事务回滚: rollBackFor: 如:rollbackFor = {FileNotFoundException.class} rollbackForClassName: 如:rollbackForClassName = {"java.io.FileNotFoundException"}
AOP基于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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <context:component-scan base-package="com.fan"></context:component-scan> <context:property-placeholder location="classpath:db.properties"></context:property-placeholder> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="username" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> <property name="url" value="${jdbc.url}"></property> <property name="driverClassName" value="${jdbc.driverName}"></property> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> <!--事务的配置--> <!--声明一个事务管理器--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <aop:config> <aop:pointcut id="exPointcut" expression="execution(* com.fan.service.*.*(..))"/> <!--事务建议--> <aop:advisor advice-ref="myAdvice" pointcut-ref="exPointcut"></aop:advisor> </aop:config> <tx:advice id="myAdvice" transaction-manager="transactionManager" > <!--配置事务的属性--> <tx:attributes> <!--配置在哪些方法上添加事务以及事务的传播特性--> <tx:method name="addBook" propagation="REQUIRED" read-only="true"/> <tx:method name="updatePrice" propagation="REQUIRED"></tx:method> <!--方法名称支持通配符--><!-- <tx:method name="*" propagation="REQUIRED"></tx:method>--> </tx:attributes> </tx:advice></beans>
优点
\t1、Spring通过DI、AOP和消除样板式代码来简化企业级Java开发
\t\t2、Spring框架之外还存在一个构建在核心框架之上的庞大生态圈,它将Spring扩展到不同的领域,如Web服务、REST、移动开发以及NoSQL
\t\t3、低侵入式设计,代码的污染极低
\t\t5、Spring的IoC容器降低了业务对象替换的复杂性,提高了组件之间的解耦
\t\t6、Spring的AOP支持允许将一些通用任务如安全、事务、日志等进行集中式处理,从而提供了更好的复用
\t\t7、Spring的ORM和DAO提供了与第三方持久层框架的的良好整合,并简化了底层的数据库访问
\t\t8、Spring的高度开放性,并不强制应用完全依赖于Spring,开发者可自由选用Spring框架的部分或全部
简化开发
\t\t基于POJO的轻量级和最小侵入性编程
\t\t通过依赖注入和面向接口实现松耦合
\t\t基于切面和惯例进行声明式编程
\t\t通过切面和模板减少样板式代码
8个模块
Test
Core Container
Beans
Core
Context
SpEL(Spring Expression Lanuage)
AOP
Aspects
Instrumentation
Messaging
Web
WebSocket
Servelt
Portlet
Data Access/Integration
JDBC
ORM(Object Releation Mapping)
OXM(Object XML Mapping)
JMS(Java Message Service)
Transactions
jar包下载
https://repo.spring.io/release/
0 条评论
回复 删除
下一页