首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >静态查找需要@Transactional但没有@Transactional的方法

静态查找需要@Transactional但没有@Transactional的方法
EN

Stack Overflow用户
提问于 2013-05-10 06:18:58
回答 1查看 130关注 0票数 0

为了避免数据库连接泄漏,可以将c3p0配置为让您知道发生连接泄漏的时间,并指出问题代码:

代码语言:javascript
复制
<property name="unreturnedConnectionTimeout" value="900"/>  <!-- seconds -->
<property name="debugUnreturnedConnectionStackTraces" value="true"/>

最好在部署它们之前捕获它们。也就是说,在构建时静态地捕获它们。似乎可以1)识别DAO类型的类,或者这样注释,或者通过hbm文件,然后2)向上跟踪调用树并标记没有标记为@Transactional的方法。即使有一些误报,这也是一个有用的工具来帮助消除这个问题。诸如IntelliJ和Eclipse之类的IDE已经知道如何查找方法的调用者。

有没有开源工具可以做这样的事情?即使它没有完成第一步,手动识别DAO也很容易。这是从自动化解决方案中获益最多的第二部分。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-05-10 07:19:05

我在Spring应用程序中遇到了类似的问题,并编写了一个在应用程序启动时运行的bean处理器,并在初始化后检查每个bean。这不是一个编译时解决方案,但是假设您在生产之前的某个地方运行了应用程序,那么您将有机会找到缺少注释的方法。

它查找带有@Service注释的类,遍历该类实现的接口,并检查每个接口的方法。它查找的方法要么没有定义任何方法级安全性,要么有一个自定义的@Unsecured注释,这表明我们已经发现该方法缺乏安全性,但确定它不需要安全性。任何缺乏安全性和@Unsecured注释的方法都会被记录下来。

下面的代码一度可以工作,但在旧版本的Spring中使用。我不知道它能否与Spring3.x一起工作,但如果不能,一个类似的方法应该仍然有效。您可能需要调整检查逻辑以满足您的需求(例如,查找具有不同类级注释的类,检查类本身的方法而不是该类实现的接口中的方法,等等)。请注意,我的方法没有尝试遍历调用树,因此您可能会得到更多的误报(即,并非所有服务方法最终都调用DAO方法)。

代码语言:javascript
复制
public class UnsecuredServiceMethodProcessor implements BeanPostProcessor {
    private static final Logger logger = LogManager.getLogger(UnsecuredServiceMethodProcessor.class);
    private final MethodSecurityInterceptor interceptor;

    public UnsecuredServiceMethodProcessor(MethodSecurityInterceptor interceptor) {
        this.interceptor = interceptor;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName)
            throws BeansException {
        Class<?> beanClass = bean.getClass();
        if (logger.isInfoEnabled()) {
            logger.info("checking bean " + beanName + " of type " + beanClass.getName());
        }
        for (Class<?> interfaceClass: beanClass.getInterfaces()) {
            checkClass(beanClass, interfaceClass);
        }

        return bean;
    }

    /**
     * @param beanClass
     * @param interfaceClass
     */
    private void checkClass(Class<?> beanClass, Class<?> interfaceClass) {
        if (interfaceClass.isAnnotationPresent(Service.class)) {
            if (logger.isDebugEnabled()) {
                logger.debug("found service implementation: " + interfaceClass + " on " + beanClass);
            }
            for (Method method: interfaceClass.getMethods()) {
                if (!method.isAnnotationPresent(Unsecured.class)) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("checking " + method.getName());
                    }
                    MethodSecurityMetadataSource msms = interceptor.getSecurityMetadataSource();
                    Collection<ConfigAttribute> atts = msms.getAttributes(method, interfaceClass);
                    if (atts == null || atts.size() == 0) {
                        logger.warn("unsecured method: " +  method.getDeclaringClass().getName() + "." + method.getName());
                    }
                }
            }
        }
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName)
            throws BeansException {
        return bean;
    }

}

您需要在应用程序上下文中显式定义此类型的bean,或者添加@Component类级别注释并扫描它。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16472073

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档