Spring核心框架里面,最关键的两个机制,就是IOC和AOP,根据xml配置或者注解,去实例化所有的bean,管理bean之间的依赖注入,让类与类之间解耦,维护代码的时候可以更加轻松便利。
Spring已经管理了我们代码里所有类的对象实例,
如以下两个交由Spring容器管理的类,每个业务方法内可能都有多个增删改的操作:
@Controller
public class MyController{
@Resource
private MyServiceA myServiceA;
public void doRequest(){
myServiceA.doServiceA();
}
}
@Service
public class MyServiceAImpl implements MyServiceA{
public void doServiceA(){
//开启事务
//insert语句
//update语句
//update语句
//delete语句
//如果有任何一个语句失败了,则回滚事务
//如果大家都成功了,则提交事务
}
}
@Service
public class MyServiceBImpl implements MyServiceB{
public void doServiceB(){
//开启事务
//update语句
//update语句
//insert语句
//如果有任何一个语句失败了,则回滚事务
//如果大家都成功了,则提交事务
}
}
事务机制:如果开启一个事务,在这个事务里执行多条增删改的sql语句,这个过程中,如果任何一个sql语句失败了,会导致这个事务的回滚,把其他sql做的数据更改都恢复回去。
在一个事务里的所有sql,要么一起成功,要么一起失败,事务功能可以保证我们的数据一致性。
如果现在有几十个这样的Service组件,有类似开启和关闭事务一样的代码,重复的代码必须在几十个地方都去写一摸一样的东西,则会特别麻烦。
当引入Spring的AOP机制时,这样的问题就会变得比较好解决了:
做一个切面:将MyServiceXXXX的这种类,在这些类的所有方法中,在所有这些方法刚开始运行的时候,都去织入开启事务的代码;在所有这些方法运行完毕之后,去根据是否抛出异常来判断,如果抛出异常,就回滚事务,如果没有异常,就提交事务。
AOP机制的核心技术是动态代理技术。定义好切面后,Spring在运行的时候,会运用动态代理技术,去给相应的类生成动态代理对象;
如:
public class ProxyMyServiceA implements MyServiceA{
private MyServiceA myServiceA ;
public void doServiceA(){
//开启事务
//直接调用MyServiceA对象的方法
myServiceA.doServiceA();
//根据是否抛出异常,回滚事务,或者提交事务
}
}
Spring会将ProxyMyServiceA这个动态代理类去注入到MyController中的myServiceA对象。
@Controller
public class MyController{
@Resource
private MyServiceA myServiceA; //注入的是动态代理的对象实例ProxyMyServiceA
public void doRequest(){
myServiceA.doServiceA(); //直接调用到动态代理的对象实例的方法中去
}
}
总结:
对于一些实现了接口的类,如果这些类要去加入一下功能很相似的代码,比如开启事务和关闭事务。
可以去定义一个切面,定义好切面,对符合某种规则的一批类进行处理,织入一些增强的代码,生成相应的动态代理对象,该代理对象和之前的类实现了相同的接口,并且在依赖注入时会注入新生成的动态代理对象实例。