Spring 学习笔记

来源:互联网 发布:afnetworking上传json 编辑:程序博客网 时间:2024/05/21 18:47

Spring

这里写图片描述

IOC&DI概述

IOC是一种思想,即控制反转,

将控制的权限给了IOC容器,对象被动的依赖参数的注入。

不同于以往主程序是老大,主程序创建对象调用方法获取参数,而是将对象的创建,参数的获取和修改放在了xml配置文件中。利用IOC容器,调用需要的bean创建对象,同时注入需要的value值。

自动装配bean

自动注入需要的bean

xml中<bean>标签里带有autowire属性

参数:

byName:根据id,装配指定的已有的bean,要求bean的id与类中setter方法的name(setName的name)一致,(与参数无关,若没有对应id的,则装配null)

byType:将对应类型的bean装配(类型指class),要求IOC容器有且仅有一个符合类型(class)的bean,否则抛异常

Bean的生命周期

这里写图片描述

Bean中带有初始化和销毁方法的引用

init-method

destroy-method

具体方法需在注入类中实现

实现接口BeanPostProcessor

这里写图片描述

<!-- 配置bean的后置处理器,不需要配置id,IOC容器自动识别是一个BeanPostProcessor --><bean class="com.mar.spring.beans.MyBeanPostProcessor">

方法中的参数

bean:bean本身

beanName:IOC容器配置的bean的名字

返回值:是实际上返回给用户的那个bean

注意:可以在以上两个方法中修改返回的bean类,甚至是另一个bean类

Object postProcessBeforeInitialization(Object bean, String beanName)

方法在init-method之前实现

Object postProcessAfterInitialization(Object bean, String beanName)

方法在init-method之后被实现

工厂bean的配置方法

这里写图片描述

静态工厂方法

创建静态工厂方法,静态代码块中配置<String,Bean>键值对,

创建静态getter方法return需要的bean对象.

配置xml中bean实例,添加factory-method确认getter方法,使用构造入参获取value值

class:指向静态工厂方法的全类名

factory-method:指向静态工厂方法的名字

constructor-arg:配置传入参数

实例化工厂方法

创建实例工厂方法,构造方法中配置<String,Bean>键值对,

创建getter方法return需要的bean对象.(非静态)

配置xml中工厂实例和bean实例,

<!-- 配置工厂的实例 --><bean id="carFactory" class="com.mar.factory.InstanceCarFactory"></bean><!-- 通过实例工厂方法来配置bean --><bean id="car2" factory-bean="carFactory" factory-method="getCar"><constructor-arg value="audi"></constructor-arg></bean>

通过fanctory-bean和factory-method确认工厂bean和工厂方法,<constructor-arg>获取参数

通过FactoryBean实例创建

创建类,继承FactoryBean接口,重写实现类方法。

getObject():返回bean的对象

getObjectType():返回bean的类型

isSingleton():返回对象是否是单例

xml配置:

<bean id="name" class="com...FactoryBean" ></bean>

class:指向FactoryBean的全类名

property:配置FactoryBean的属性

通过注解配置bean

xml中配置<context:component-scan base-package=""></context:component-scan>

自动扫描包

@Component

@Respository dao层

@Service service层

@Controller web层

这两个经常一起用,自动装配,同时指定装配的bean

@Autowired

@Qualifier(“”)

同时可配置子节点

context:exclude-filter

context:include-filter

指定包含和不包含的包

例:

<context:exclude-filter type="annotation"

expression="org.springframework.stereotype.Repositorya " />

type指定过滤类型,

annotation:注解

assignable:全类名

aspectj:AspectJ语法

regex:Regelar Expression

use-default-filter:开启是否使用自定义过滤器

泛型依赖注入

bean的作用域

xml配置bean - scope作用域

AOP

这里写图片描述

Spring AOP

(使用了AspectJ)

1、相关jar包

(AspectJ相关)

com.springsource.org.aopalliance-1.0.0.jar

com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar

spring-aop-4.0.0.RELEASE.jar

spring-aspects-4.0.0.RELEASE.jar

(Spring相关)

com.springsource.net.sf.cglib-2.2.0.jar

commons-logging-1.1.1.jar

spring-beans-4.0.0.RELEASE.jar

spring-context-4.0.0.RELEASE.jar

spring-core-4.0.0.RELEASE.jar

spring-expression-4.0.0.RELEASE.jar

2、在配置文件中加入aop的命名空间

3、基于注解的方式

1、在配置文件中加入如下配置:

<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

2、把横切关注点的代码抽象到切面的类中

1、切面首先是一个IOC中的bean,即加入@Component注解

2、切面还需要加入@AspectJ注解

3、在类中声明各种通知

@Before:前置通知

@After:后置通知

@AfterThrowing:异常通知,在方法抛出异常之后

@AfterReturning:返回通知,在方法返回结果之后

@Around:环绕通知,围绕着方法执行

4、可以在通知方法中声明一个类型为 JoinPoint 的参数,然后就能访问连接细节,如,方法名称和参数值

public void afterMethod(JoinPoint joinPoint){String methodName = joinPoint.getSignature().getName();Object[] args = joinPoint.getArgs();System.out.println("the method "+ methodName +" ends..."+ Arrays.asList(args));}

AOP底层

动态代理

InvocationHandler重写方法

@Overridepublic Object invoke(Object proxy,Method method,Object[] args){String methodName = method.getname();Object result = null;try{//前置通知result = method.invoke(target,args);//返回通知,可以访问到返回值}catch (Exception e){e.printStackTrace();//异常通知,可以访问到方法}//后置通知,因为方法可能异常,所以访问不到返回值return result;}

基于AspectJ注解方式

这里写图片描述

前置通知

@Before(“execution(public com.mar.*(int ,int))”)

后置通知

@After(“execution(public com.mar.*(int ,int))”)

后置通知是在连接点完成之后执行的,即连接点返回结果或者抛出异常的时候,下面的后置通知记录了方法的终结

一个切面可以包括一个或者多个通知(Advice)

后置通知中不能访问目标方法的执行结果,

只有返回通知(AfterRunning)能访问

返回通知

@AfterReturning

异常通知

/** 在目标方法出现异常时会执行的代码* 可以访问到异常对象;且可以指定在出现特定异常时再执行通知代码*/@AfterThrowing(value="execution(public int com.mar.spring.aop.impl.ArithmeticCalculator.*(..))",throwing="ex")public void afterThrowing(JoinPoint joinPoint ,Exception ex){String methodName = joinPoint.getSignature().getName();System.out.println("the method "+ methodName +" occurs excetion "+ ex);}

环绕通知

@Around/** 环绕通知需要携带ProceedingJoinPoint类型的参数* 环绕通知类似于动态代理的全过程:ProceedingJoinPoint可以决定是否执行目标方法* 且必须要有返回值,返回值即为目标方法的返回值*/@Around("execution(public int com.mar.spring.aop.impl.ArithmeticCalculator.*(..))")public Object aroundMethod(ProceedingJoinPoint pdj){Object result = null;String methodName = pdj.getSignature().getName();//执行目标方法try {//前置通知System.out.println("aroundMethod.."+ methodName);//执行目标方法result = pdj.proceed();//返回通知System.out.println("ends..."+result);} catch (Throwable e) {//异常通知e.printStackTrace();}//后置通知return result;}

优先级

@Order(1)

使用order注解标记优先级,值越小,优先级越高

注解Advice书写重复解决方案

@Pointcut

/*

  • 定义一个方法,用于声明切入点表达式。一般地,该方法中不需要添入其它代码

  • 用途:解决注解中Advice的重复书写

  • 其他java类中,可以使用(包名)类名加方法名使用

  • 例:LoggingAspect.declareJointPointExpression()

*/

@Pointcut(“execution(public int com.mar.spring.aop.impl.ArithmeticCalculator.*(..))”)

public void declareJointPointExpression(){}

@Before(value=”declareJointPointExpression()”)

public void beforeMethod(JoinPoint joinPoint){

String methodName = joinPoint.getSignature().getName();

Object[] args = joinPoint.getArgs();

System.out.println(“the method “+ methodName +” begins…”+ Arrays.asList(args));

}

//***************************************

VlidationAspect.java

@Aspect

@Component

@Order(1)//指定优先级 ,值越小,优先级越高

public class VlidationAspect {

@Before(“LoggingAspect.declareJointPointExpression()”)

public void validateArgs(JoinPoint joinPoint){

System.out.println(“validate:” + Arrays.asList(joinPoint.getArgs()));

}

}

基于xml配置方式

//详情见spring-3项目com.mar.spring.aop.xml下

<!-- 配置bean --><bean id="arithmeticCalculator"class="com.mar.spring.aop.xml.ArithmeticCalculatorImpl"></bean><!-- 配置切面bean --><bean id="loggingAspect"class="com.mar.spring.aop.xml.LoggingAspect"></bean><bean id="vlidationAspect"class="com.mar.spring.aop.xml.VlidationAspect"></bean><!-- 配置AOP --><aop:config><!-- 配置切点表达式 --><aop:pointcut expression="execution(* com.mar.spring.aop.xml.ArithmeticCalculator.*(int , int ))"id="pointcut"/><!-- 配置切面aspect及通知advice --><aop:aspect ref="loggingAspect" order="2"><aop:before method="beforeMethod" pointcut-ref="pointcut"/><aop:after method="afterMethod" pointcut-ref="pointcut"/><aop:after-throwing method="afterThrowing" pointcut-ref="pointcut" throwing="ex"/><aop:after-returning method="afterReturning" pointcut-ref="pointcut" returning="result"/></aop:aspect></aop:config>

spring JDBC框架

这里写图片描述

jdbcTemplate

jdbcDaoSupport

具名参数

事务

这里写图片描述

事务管理是企业级应用程序开发中必不可少的技术,用来确保数据的完整性和一致性

事务就是一系列的动作,它们被当作一个独立的工作单元。这些动作要么完成,要么全部不起作用

事务的四个关键属性ACID

  • 原子性(atomicity):事务是一个原子操作,由一系列动作组成,事务的原子性确保动作要么全部完成,要么全部不起作用

  • 一致性(consistency):一旦所有失误动作完成,事务就要被提交。数据和资源就处于一种满足业务规则的一致性状态中。

  • 隔离性(isolation):可能有许多事务会同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏。

  • 持久性(durability):一旦事务完成,无论发生什么系统错误,它的结果都不应该受到影响,通常情况下,事务的结果被写到持久化存储器中。

声明式事务

这里写图片描述

基于注解的方式

这里写图片描述

<!-- 配置事务管理器 --><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property></bean><!-- 启用事务注解 --><tx:annotation-driven transaction-manager="transactionManager" />
@Transactional事务注解

带有该注解的方法,一但出异常,抛出异常后,自动回滚

1、事务的传播属性

  • 当事务方法的另一个事务方法调用时,必须指定事务应该如何传播,例如:方法可能继续在现有事务中运行,也可能开启了一个新事务,并在自己的事务中运行

  • 事务的传播行为可以有传播属性指定,Spring定义了7种类传播行为

传播属性(常用)

REQUIRED(默认) 如果有事务在运行,当前的方法就在这个事务内运行,(回滚到上一个事务的起点)否则,就起用一个新的事务,并在自己的事务内运行

REQUIRED_NEW 当前的方法必须启动新事物,并在它自己的事务内运行,如果有事务正在运行,应该将它挂起(回滚到自己事务的起点)

使用propagation指定事务的传播行为

@Transactional(propagation=Propagation.REQUIRED)

2、事务的隔离级别

最常用的取值READ_COMMITTED

@Transactional(isolation=Isolation.READ_COMMITTED)

3、事务默认情况下对所有的运行时期异常回滚,

也可以通过对应的属性进行设置

@Transactional(noRollbackFor={UserAccountException.class})

4、事务的只读,指定事务是否为只读,表示这个事务只读取数据不更新数据,这样可以帮助数据库优化事务

@Transactional(readOnly=true)

5、事务的过期

指定强制回滚之前,事务可以占用的时间,防止一个事务对运行占用时间过长,单位/秒

@Transactional(timeout=1)

基于xml的方式

<!-- 1、配置事务管理器 --><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property></bean><!--2、配置事务属性 --><tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><tx:method name="*" /></tx:attributes></tx:advice><!-- 3、配置事务切入点,以及把事务切入点和事务属性关联起来 --><aop:config><aop:pointcut expression="execution(* com.mar.spring.tx.xml.BookShopService.*(..))" id="txPoinCut" /><aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut" /></aop:config>