IOC是一种思想,即控制反转,
将控制的权限给了IOC容器,对象被动的依赖参数的注入。
不同于以往主程序是老大,主程序创建对象调用方法获取参数,而是将对象的创建,参数的获取和修改放在了xml配置文件中。利用IOC容器,调用需要的bean创建对象,同时注入需要的value值。
自动注入需要的bean
xml中
标签里带有autowire属性
参数:
byName:根据id,装配指定的已有的bean,要求bean的id与类中setter方法的name(setName的name)一致,(与参数无关,若没有对应id的,则装配null)
byType:将对应类型的bean装配(类型指class),要求IOC容器有且仅有一个符合类型(class)的bean,否则抛异常
init-method
和
destroy-method
具体方法需在注入类中实现
<bean class="com.mar.spring.beans.MyBeanPostProcessor">
方法中的参数
bean:bean本身
beanName:IOC容器配置的bean的名字
返回值:是实际上返回给用户的那个bean
注意:可以在以上两个方法中修改返回的bean类,甚至是另一个bean类
方法在init-method之前实现
方法在init-method之后被实现
创建静态工厂方法,静态代码块中配置
键值对,
创建静态getter方法return需要的bean对象.
配置xml中bean实例,添加factory-method确认getter方法,使用构造入参获取value值
class:指向静态工厂方法的全类名
factory-method:指向静态工厂方法的名字
constructor-arg:配置传入参数
创建实例工厂方法,构造方法中配置
键值对,
创建getter方法return需要的bean对象.(非静态)
配置xml中工厂实例和bean实例,
<bean id="carFactory" class="com.mar.factory.InstanceCarFactory">
bean>
<bean id="car2" factory-bean="carFactory" factory-method="getCar">
<constructor-arg value="audi">constructor-arg>
bean>
通过fanctory-bean和factory-method确认工厂bean和工厂方法,
获取参数
创建类,继承FactoryBean接口,重写实现类方法。
getObject():返回bean的对象
getObjectType():返回bean的类型
isSingleton():返回对象是否是单例
xml配置:
<bean id="name" class="com...FactoryBean" >bean>
class:指向FactoryBean的全类名
property:配置FactoryBean的属性
xml中配置
自动扫描包
@Component
@Respository dao层
@Service service层
@Controller web层
这两个经常一起用,自动装配,同时指定装配的bean
@Autowired
@Qualifier(“”)
同时可配置子节点
context:exclude-filter
context:include-filter
指定包含和不包含的包
例:
expression="org.springframework.stereotype.Repositorya " />
type指定过滤类型,
annotation:注解
assignable:全类名
aspectj:AspectJ语法
regex:Regelar Expression
use-default-filter:开启是否使用自定义过滤器
xml配置bean - scope作用域
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、在配置文件中加入如下配置:
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));
}
动态代理
InvocationHandler重写方法
@Override
public 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;
}
@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注解标记优先级,值越小,优先级越高
@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()));
}
}
//详情见spring-3项目com.mar.spring.aop.xml下
<bean id="arithmeticCalculator"
class="com.mar.spring.aop.xml.ArithmeticCalculatorImpl">bean>
<bean id="loggingAspect"
class="com.mar.spring.aop.xml.LoggingAspect">bean>
<bean id="vlidationAspect"
class="com.mar.spring.aop.xml.VlidationAspect">bean>
<aop:config>
<aop:pointcut expression="execution(* com.mar.spring.aop.xml.ArithmeticCalculator.*(int , int ))"
id="pointcut"/>
<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>
事务管理是企业级应用程序开发中必不可少的技术,用来确保数据的完整性和一致性
事务就是一系列的动作,它们被当作一个独立的工作单元。这些动作要么完成,要么全部不起作用
事务的四个关键属性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" />
带有该注解的方法,一但出异常,抛出异常后,自动回滚
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)
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource">property>
bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" />
tx:attributes>
tx:advice>
<aop:config>
<aop:pointcut expression="execution(* com.mar.spring.tx.xml.BookShopService.*(..))" id="txPoinCut" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut" />
aop:config>