如何建立公司网站链接手机立体房屋设计软件
web/
2025/10/1 23:17:32/
文章来源:
如何建立公司网站链接,手机立体房屋设计软件,jsp网站购买空间,汕头h5建站模板spring和spring在初始化应用程序上下文时#xff0c;Spring在遇到带有Transactional标记的类时会创建代理。 Transactional可以应用于类级别或方法级别。 在类级别应用它意味着该类中定义的所有公共方法都是事务性的。 Spring创建的代理类型#xff0c;即Jdk代理或CGLIB代理Spring在遇到带有Transactional标记的类时会创建代理。 Transactional可以应用于类级别或方法级别。 在类级别应用它意味着该类中定义的所有公共方法都是事务性的。 Spring创建的代理类型即Jdk代理或CGLIB代理取决于将方法标记为事务性的类。 如果该类实现了至少一个接口则Spring将创建一个Jdk动态代理。 该代理实现与原始类相同的接口并使用事务维护逻辑拦截接口方法。 它将调用委托给其中组成的原始对象。 假设该类未实现任何接口Spring将创建一个CGLIB代理。 该代理扩展了原始类并覆盖了公共方法。 我们将尽快对此进行仔细研究。 假设我们有一个这样定义的类 public interface BookDao{void buyBook(String isbn) throws BookNotFoundException;Book findByIsbn(String isbn);int deductStock(Book book);
}public class JdbcBookDao implements BookDao{void buyBook(String isbn) throws BookNotFoundException{Book book findByIsbn(isbn);if(book null){throw new BookNotFoundException();}deductStock(book);}Transactional(propagationPropagation.REQUIRES_NEW)Book findByIsbn(String isbn){Book book getJdbcTemplate().queryForObject(SELECT * FROM BOOK WHERE ISBN?,ParameterizedBeanPropertyRowMapper.newInstance(Book.class), isbn);return book;}Transactional(propagationPropagation.REQUIRES_NEW)int deductStock(Book book){String sql UPDATE BOOK_STOCK SET STOCKSTOCK-1 WHERE BOOK_ID?;return getJdbcTemplate().update(sql, stockIncrement, book.getId());}
} 现在Spring是否会通过从main方法调用bookDao的findByIsbn自动创建交易 否。我们必须在xml配置中声明这一点 tx:annotation-driven 因此如果它不创建事务是否会引发错误 答案还是不是。Spring非事务地执行此语句。 正如我们所期望的那样一旦声明了‹txannotation-driven›Spring将在该类实现接口时为JdbcBookDao创建一个Jdk动态代理。 现在说我们调用JdbcBookDao的buyBook方法Spring创建了多少个事务 二1用于findByIsbn另外1用于deductStock。 一在同一笔交易中同时找到findByIsbn和deductStock。 完全没有交易 答案是3。 交易的默认交易模式为“代理”。 这意味着Spring仅考虑通过代理进行的方法调用进行自动事务管理。 现在如果您仔细观察buyBook方法不会标记为事务性的。 因此当创建事务代理时该方法不会被事务管理逻辑拦截因为它未标记为Transactional。 简而言之buyBook不会在代理中被覆盖。 因此该方法直接在原始对象上调用。 因此其他两个方法也将在原始对象上调用。 请记住只有PROXY包含事务管理代码。 因此当其他方法也被原始对象调用时Spring根本不会创建事务。 现在如果我们将buyBook标记为Transactional是否可以解决问题 Spring是否会为每个findByIsbn和deductStock方法创建两个单独的事务 不会。调用buyBook时Spring仅创建一个事务。 由于不会在原始对象本身而不是代理上调用各个方法因此不会进一步创建任何新事务。 那么如何解决这个问题呢 我们可以要求Spring创建一个CGLIB proxy吗 现在由于代理是具有重写的公共事务方法的子类因此它为每个方法调用创建一个新事务 再次没有。 CGLIB代理不会直接在超类上调用该方法。 这是如何实现的粗略想法。 import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;public class MyInterceptor implements MethodInterceptor {private Object realObject;public MyInterceptor(Object original) {this.realObject original;}// This method will be called every time the object proxy calls any of its methodspublic Object intercept(Object o, Method method, Object[] args,MethodProxy methodProxy) throws Throwable {/*** Transaction Management Code*/// Invoke the method on the real object with the given paramsObject res method.invoke(realObject, args);/*** Transaction Management Code*/return res;}
}import net.sf.cglib.proxy.Enhancer;public class ProxyCreator(){public static T createProxy(T original){// Enhancer is CGLIB class which builds a dynamic proxy with new capabilitiesEnhancer e new Enhancer();e.setSuperclass(original.getClass());// We have to declare the interceptor whose intercept will be called when methods are called on proxy.e.setCallback(new MyInterceptor(original));T proxy (T) e.create();return proxy;}
} 因此正如您在此处看到的代理扩展了原始类并由其对象组成。 因此当我们调用buyBook时代理会创建一个事务并将该调用委托给原始对象。 从原始对象的buyBook中调用findByIsbn和deductStock不会因此不会创建新的交易。 一个快速的周转解决方案是因为JdbcBookDao是一个单例请从应用程序上下文中获取此对象。 现在与其直接在对象上调用方法不如使用引用来调用它以确保调用代理这就是方法的外观。 public class JdbcBookDao implements BookDao, ApplicationContextAware{private ApplicationContext context;private BookDao bookDao;public void setApplicationContext(ApplicationContext context){this.context context;}public BookDao getBookDao(){bookDao (BookDao)context.getBean(jdbcBookDao);}void buyBook(String isbn) throws BookNotFoundException{Book book getBookDao().findByIsbn(isbn);if(book null){throw new BookNotFoundException();}getBookDao().deductStock(book);}.....
} 刚刚实施了一个粗略的版本来使它正常工作。 我们绝对可以改进它的设计方式。 代替将应用程序上下文直接注入到DAO中可能是我们可以使用一种辅助类来做到这一点。 或者完成此任务的另一种方法是使用程序化事务。 最后要注意的一点是Spring仅在将公共方法标记为事务性时才管理事务。 对于私有受保护和程序包私有的方法Spring不提供事务管理支持。 对于动态代理当它们实现接口时所有事务处理方法都是公共的。 因此无需担心非公开方法。 对于CGLIB代理在创建子类时仅重写公共方法。 因此即使在这里也不会考虑非公开方法。 让我以一个问题结束这次讨论。 当我尝试使用‹txannotation-driven proxy-target-class ” true” /›代理目标类时它实际上不起作用即未创建CGLIB代理 。 为此我必须进行一些小改动。 正如Spring文档明确指出的那样如果在‹txannotation驱动的›‹aopconfig›或‹aopaspectj-autoproxy›中的任何一个上启用了代理目标类Spring将在容器上启用CGLIB代理创建。 因此我只创建了一个空的‹aopconfig proxy-target-class “ true” /›。 不用担心它开始起作用 不知道这是否是Spring本身的错误。 高度赞赏如果有人可以回答这个问题。 参考 Spring交易可见性来自prasanthnath博客上的JCG合作伙伴 Prasanth Gullapalli。 翻译自: https://www.javacodegeeks.com/2013/11/spring-transactions-visibility.htmlspring和spring
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/85302.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!