The filter-chain design pattern of Alibaba druid source code analysis

Druid is known as the best java database connection pool at present. There are many design patterns in the code written by Wen Shao, and the most important one is the scalability brought by the filter-chain design pattern to Druid. I am very interested in this, and hope to learn from it in the future, so I looked at his source code and recorded it.

The classes or interfaces designed into the filter-chain design pattern in druid mainly include the following Filter, FilterAdapter, FilterChain, FilterChainImpl, FilterEventAdapter, FilterManager and two specific filters: StatFilter, Slf4jLogFilter

 

The specific responsibilities are divided as follows:

Filter interface: defines the events that the filter needs to pay attention to and the events that can be handled

 

FilterChain interface: defines the events that this filter chain can handle. In the design of druid, these two interfaces are almost the same.

 

FilterChainImpl implementation class: mainly has two specific functions, one is to specifically handle the specific events in the chain; the other is to distribute the request to the next filter' "processing", note that the processing here is not to handle this event , but do some doBefore, doAfter events.

 

FilterEventAdapter class: Divide the specific events we are concerned about into three events: doBefore, do, and doAfter through the design mode of the adapter

StatFilter, Slf4jLogFilter classes: implement doBefore, doAfter, in this case, the classes configured with these two filters can do some aspects.

 

FilterManager class: A tool class that provides the spi method of loading filters. It is also a kind of decoupling, which decouples filter and chain to facilitate future expansion.

 

Example database connection process

The interface of the filter, each filter can only temporarily own the chain, and each chain owns the filter:

ConnectionProxy connection_connect(FilterChain chain, Properties info) throws SQLException;

 In the FilterChain interface, in druid, the final implementation of the specific method is FilterChainImpl,

ConnectionProxy connection_connect(Properties info) throws SQLException;
 int getFilterSize();

 How exactly does FilterChainImpl implement calling and dispatching requests? please see

public ConnectionProxy connection_connect(Properties info) throws SQLException {
        if (this.pos < filterSize) {
            return nextFilter().connection_connect(this, info);
        }

        Driver driver = dataSource.getRawDriver();
        String url = dataSource.getRawJdbcUrl();

        Connection nativeConnection = driver.connect(url, info);
        return wrap(nativeConnection, info);
    }

 From here, we can see that there is no need to do each filter specifically for the connection of the specific database. Why, because the specific database connection step is fixed, it cannot be written, and every filter is not needed. To implement, so, filterChainImpl did it for us. This is also the difference between filter-chain and other chains. Its filter pays more attention to the processing of aspects. And it doesn't seem to see how to distribute it here.

Please see the code below:

  private Filter nextFilter() {
        Filter filter = getFilters().get(pos++);
        return filter;
    }

 In fact, he just traversed the list, remembered the offset of the list, and took out the filters one by one.

ok, here we can see how the filter handles events. According to the above, each event is divided into doBefore, do, doAfter so where is this divided? At this time, the FilterEventAdapter class is introduced.

  public ConnectionProxy connection_connect(FilterChain chain, Properties info) throws SQLException {
        connection_connectBefore(chain, info);

        ConnectionProxy connection = super.connection_connect(chain, info);

        connection_connectAfter(connection);

        return connection;
    }

    public void connection_connectBefore(FilterChain chain, Properties info) {

    }

    public void connection_connectAfter(ConnectionProxy connection) {

    }

 See, it is divided into three events, so we can be sure that each filter is an inherited FilterEventAdapter

public ConnectionProxy connection_connect(FilterChain chain, Properties info) throws SQLException {
        ConnectionProxy connection = null;
        {
            long startNano = System.nanoTime ();
            long startTime = System.currentTimeMillis();

            long nanoSpan;
            long nowTime = System.currentTimeMillis();

            JdbcDataSourceStat dataSourceStat = chain.getDataSource().getDataSourceStat();
            dataSourceStat.getConnectionStat().beforeConnect();
            try {
                connection = chain.connection_connect(info);
                nanoSpan = System.nanoTime () - startNano;
            } catch (SQLException ex) {
                dataSourceStat.getConnectionStat().connectError(ex);
                throw ex;
            }
            dataSourceStat.getConnectionStat().afterConnected(nanoSpan);

            if (connection != null) {
                JdbcConnectionStat.Entry statEntry = getConnectionInfo(connection);

                dataSourceStat.getConnections().put(connection.getId(), statEntry);

                statEntry.setConnectTime(new Date(startTime));
                statEntry.setConnectTimespanNano(nanoSpan);
                statEntry.setEstablishNano (System.nanoTime ());
                statEntry.setEstablishTime (nowTime);
                statEntry.setConnectStackTrace(new Exception());

                dataSourceStat.getConnectionStat().setActiveCount(dataSourceStat.getConnections().size());
            }
        }
        return connection;
    }

 As you can see from the code marked in red, as expected, Druid's filter-chain is designed in this way. The FilterManager tool class does not need to be introduced too much.

 

oracle interceptor-filter design pattern

http://www.oracle.com/technetwork/java/interceptingfilter-142169.html

 

 

 

 

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=327081077&siteId=291194637