为了避免数据库连接泄漏,可以配置c3p0以告知您何时发生,并指向问题代码:
<property name="unreturnedConnectionTimeout" value="900"/> <!-- seconds -->
<property name="debugUnreturnedConnectionStackTraces" value="true"/>
在部署之前,最好先抓住它们。也就是说,在构建时静态捕获它们。似乎可以1)识别DAO类型的类,或者通过注释或者通过hbm文件,然后2)向上跟踪调用树并标记未标记为@Transactional的方法。即使存在一些误报,这也是帮助消除此问题的有用工具。诸如IntelliJ和Eclipse之类的IDE已经知道如何找到方法的调用者。
是否有一个开源工具可以做这样的事情?即使它没有做第一步,也很容易手动识别DAO。它是第二部分,它将从自动化解决方案中获益最多。
答案 0 :(得分:1)
我在Spring应用程序中遇到了类似的问题,并编写了一个在应用程序启动时运行的bean处理器,并在初始化之后检查了每个bean。它不是编译时的解决方案,但假设您在生产之前的某个地方运行应用程序,您将有机会找到缺少相关注释的方法。
它查找了带有@Service注释的类,迭代了该类实现的接口,并检查了每个接口的方法。它查找的方法要么没有定义任何方法级安全性,要么有自定义@Unsecured
注释,表明我们已经发现该方法缺乏安全性但确定它不需要安全性。
@Unsecured
注释缺少任何安全性和的方法。
以下代码在某一点上有效,但与旧版本的Spring一起使用。我不知道它是否适用于Spring 3.x,但如果没有,类似的方法仍然可以工作。您可能需要调整检查逻辑以满足您的需求(例如,查找具有不同类级别注释的类,检查类本身的方法而不是类实现的接口中的方法等)。请注意,我的方法并没有尝试遍历调用树,因此您可能会得到更多的误报(即并非所有服务方法最终都会调用DAO方法)。
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
类级别注释并对其进行扫描。