简体   繁体   English

Spring AOP异常处理

[英]Spring AOP Exception Handling

I'm trying to check if some database hosts are alive. 我正在尝试检查某些数据库主机是否还存在。 ConfigReader class parses a xml file and gets the list of some database hosts. ConfigReader类解析xml文件并获取一些数据库主机的列表。 I want to see logs like this if some hosts are not available: 如果某些主机不可用,我想查看这样的日志:

running check for host:dbhost1 
Some Exception is ...
running check for host:dbhost2 
host is alive

and so on. 等等。

But I see this exception if the host is not alive. 但是,如果主机不存在,我会看到此异常。 The application exits instead of logging and throwing the exception. 应用程序退出,而不是记录并引发异常。

#### running check for host:dbhost1
Exception in thread "main" java.sql.SQLException: Cannot create PoolableConnectionFactory (I/O-Fehler: The Network Adapter could not establish the connection)
    at org.apache.commons.dbcp2.BasicDataSource.createPoolableConnectionFactory(BasicDataSource.java:2291)
    at org.apache.commons.dbcp2.BasicDataSource.createDataSource(BasicDataSource.java:2038)
    at org.apache.commons.dbcp2.BasicDataSource.getConnection(BasicDataSource.java:1533)
    at com.csinfra.jdbmon.app.CheckDatabase.runCheckGroup(CheckDatabase.java:108)

Here are the classes: 这些是类:

@Component
public class ScheduleCheck {
    public ConfigReader configReader;
    public CheckDatabase checkDatabase;

    public void runHostCheck() throws Exception {
        configReader.readConfig();  
        checkDatabase.setConfigReader(configReader);        
        for(Host host:configReader.getHostMap().values()){              
                System.out.println("#### running check for host:"+host.getId());
                checkDatabase.runCheckGroup(host, getCheckFromCheckGroup(host));                        
        }
    }
}



@Component
public class CheckDatabase {
    public void runCheckGroup(Host host) throws Exception{              
            createConnections(host.getJdbcurl(), host.getJdbcuser(), host.getJdbcpassword(), host.getDriverclassname());
            Connection connection_single = jdbcPool.getConnection();
            if(connection_single!=null){                    
                System.out.println("host is alive");
            }                           
    }

    public void createConnections(String url, String username, String password, String driverClassname) throws Exception{
            jdbcPool = new BasicDataSource();                       
            jdbcPool.setDriverClassName(driverClassname);
            jdbcPool.setUsername(username);
            jdbcPool.setUrl(url);
            jdbcPool.setPassword(password);
            jdbcPool.setInitialSize(2);
            jdbcPool.setCacheState(false);
            jdbcPool.setMaxTotal(2);
            jdbcPool.setMaxWaitMillis(6000);
            jdbcPool.setMaxIdle(2);
            jdbcPool.setDefaultReadOnly(true);  
    }
}


@Configurable 
@Aspect
@Component
public class AopMethodLogger {

    private static final Logger LOGGER = RootLogger.getLogger(AopMethodLogger.class);   

    @AfterThrowing(pointcut = "execution(* com.csinfra.app..*.*(..))", throwing = "exception")
    public void logAfterThrowing(JoinPoint joinPoint, Throwable exception)  throws Throwable {
        LOGGER.debug("Some Exception is "+exception.getLocalizedMessage());
        throw exception;
    }
}


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx" 
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">

    <aop:aspectj-autoproxy proxy-target-class="true" />
    <context:component-scan base-package="com.csinfra.app />

    <bean id="aopMethod" class="com.csinfra.app.log.AopMethodLogger" />

    <bean id="scheduleCheck" class="com.csinfra.app.ScheduleCheck">
        <property name="configReader" ref="configReader" />
        <property name="checkDatabase" ref="checkDatabase" />
    </bean>

    <bean id="checkDatabase" class="com.csinfra.app.CheckDatabase">
    </bean>

</beans>

CheckDatabase.runCheckGroup throws an exception and it is not handled, thats why the application exits. CheckDatabase.runCheckGroup引发异常,并且未对其进行处理,这就是应用程序退出的原因。 Surround your call to runCheckGroup with try/catch and log the exception : 用try / catch包围对runCheckGroup的调用并记录异常:

try{
  checkDatabase.runCheckGroup(host, getCheckFromCheckGroup(host));              
 } catch(Exception e){
  System.out.println("Exception occured :"+e);
}

The number of connections to the database is limited, so creating a new connection, just to check the database is alive seems rather expensive. 与数据库的连接数是有限的,因此仅检查数据库是否存在而创建一个新连接似乎相当昂贵。 It may be better to let spring inject all available datasources : 最好让spring注入所有可用的数据源:

@Autowire
List<DataSource>dataSources;

This has also the advantage to automatically check all configured datasources, without additional configuration. 这还具有无需额外配置即可自动检查所有已配置数据源的优势。

And than iterate over those, for each doing something like 而且要遍历这些,每个人都要做类似的事情

new JdbcTemplate(dataSource).queryForInt("SELECT 1")

to check its alive. 检查它的生命。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM