@Transactional注解
Spring使用了TransactionInterceptor拦截器,该拦截器主要负责事务的管理,包括开启、提交、回滚等操作。当在方法上添加@Transactional注解时,Spring会在AOP框架中对该方法进行拦截,TransactionInterceptor会在该方法执行前后,对事务进行切面处理,Spring会基于该类生成一个代理对象,把这个代理对象作为bean。当调用这个代理对象的方法时,如果有事务处理,则会先关闭事务的自动功能,然后执行方法的具体业务逻辑,如果业务逻辑没有异常,那么代理逻辑就会直接提交,如果出现任何异常,那么直接进行回滚操作。
事务管理器
Spring还提供了多种事务管理器,包括JDBC事务管理器、Hibernate事务管理器、JTA事务管理器等等,可以满足不同数据访问层的需求。事务通知是Spring事务机制中的一个重要组成部分,主要用于判断哪些方法需要被事务管理,以及如何管理事务。
Spring事务底层实现原理
应用启动时会创建一个代理类,把事务逻辑织入到代理类中,然后用代理类替代目标类,并放入上下文容器中。当实际调用目标类的事务方法时,被代理类拦截,先执行拦截器中的事务逻辑,再执行目标类的业务逻辑,最后处理异常回滚和提交。这样就能实现简单、方便、可控的事务管理。
示例代码
这里给出一个简单的示例代码:
定义一个接口,包含需要进行事务管理的方法:
public interface UserService { void addUser(User user); void deleteUser(String id); void updateUser(User user); User getUser(String id); }
实现这个接口的目标类:
public class UserServiceImpl implements UserService { @Override public void addUser(User user) { //添加用户的业务逻辑 } @Override public void deleteUser(String id) { //删除用户的业务逻辑 } @Override public void updateUser(User user) { //更新用户的业务逻辑 } @Override public User getUser(String id) { //查询用户的业务逻辑 return null; } }
定义一个事务拦截器类:
/** * TransactionInterceptor 是一个实现了 MethodInterceptor 接口的拦截器类 */ public class TransactionInterceptor implements MethodInterceptor { /** * TransactionManager 对象,用于管理事务 */ private TransactionManager txManager; /** * 用于注入 TransactionManager 对象 * @param txManager TransactionManager 对象 */ public void setTxManager(TransactionManager txManager) { this.txManager = txManager; } /** * 实现 MethodInterceptor 接口的 invoke 方法,用于拦截指定方法 * @param invocation MethodInvocation 对象,用于获取被拦截的方法及其参数 * @return 执行方法的返回结果 * @throws Throwable 抛出异常 */ @Override public Object invoke(MethodInvocation invocation) throws Throwable { Object result; try { // 开启事务 txManager.start(); // 执行被拦截的方法,并获取方法执行的返回结果 result = invocation.proceed(); // 提交事务 txManager.commit(); } catch (Exception e) { // 回滚事务 txManager.rollback(); throw e; } return result; } }
定义一个上下文容器类:
public class ApplicationContext { private Map<String, Object> beanMap = new HashMap<>(); // 用于存放bean的map // 注册bean public void registerBean(String name, Object bean) { beanMap.put(name, bean); // 将bean存放到map中 } // 获取bean public Object getBean(String name) { Object bean = beanMap.get(name); // 从map中获取bean if (bean instanceof Advised) { // 如果bean是Advised类型,说明使用了AOP return ((Advised)bean).getTargetSource().getTarget(); // 返回目标对象 } return bean; // 返回原始对象 } }
在应用启动时,创建一个代理工厂类,使用上述事务拦截器对目标类进行代理:
/** * 代理工厂类,用于创建代理对象 */ public class ProxyFactory { /** * 创建代理对象 * @param target 目标对象,需要被代理的对象 * @param interceptor 事务拦截器,代理对象需要加入该拦截器 * @return 返回代理对象 */ public static Object createProxy(Object target, TransactionInterceptor interceptor) { DefaultAopProxyFactory proxyFactory = new DefaultAopProxyFactory(); AdvisedSupport advisedSupport = new AdvisedSupport(); advisedSupport.setTarget(target); // 设置目标对象 advisedSupport.addAdvice(interceptor); // 添加事务拦截器 return proxyFactory.createAopProxy(advisedSupport).getProxy(); // 创建代理对象并返回 } }
然后在应用启动时,创建容器并注册代理类:
public class Main { public static void main(String[] args) { ApplicationContext context = new ApplicationContext(); UserService target = new UserServiceImpl(); //创建目标类 TransactionInterceptor interceptor = new TransactionInterceptor(); interceptor.setTxManager(new TransactionManager()); //设置事务管理器 UserService proxy = (UserService) ProxyFactory.createProxy(target, interceptor); //创建代理类 context.registerBean("userService", proxy); //注册代理类到上下文容器中 //使用代理类进行业务操作 User user = new User(); context.getBean("userService").addUser(user); } }
这样,当执行代理类的方法时,就会先执行事务拦截器中的事务逻辑,再执行目标类的业务逻辑。如果出现异常,会进行回滚。这样就实现了简单、方便、可控的事务管理。