com.dianping.zebra.monitor.spring.DataSourceAutoMonitor.java Source code

Java tutorial

Introduction

Here is the source code for com.dianping.zebra.monitor.spring.DataSourceAutoMonitor.java

Source

/**
 * Project: ${zebra-ds-monitor-client.aid}
 *
 * File Created at 2011-11-9
 * $Id$
 *
 * Copyright 2010 dianping.com.
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of
 * Dianping Company. ("Confidential Information").  You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with dianping.com.
 */
package com.dianping.zebra.monitor.spring;

import com.dianping.zebra.group.jdbc.GroupDataSource;
import com.dianping.zebra.log.LoggerLoader;
import com.dianping.zebra.monitor.sql.MonitorableDataSource;
import com.dianping.zebra.shard.jdbc.ShardDataSource;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.config.*;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.core.Ordered;
import org.springframework.core.PriorityOrdered;
import org.springframework.util.ClassUtils;

import javax.sql.DataSource;
import java.util.Map;
import java.util.Map.Entry;

/**
 * springDataSourcemonitor?spring??? <bean class="com.dianping.zebra.monitor.spring.DataSourceAutoMonitor"/>
 *
 * @author danson.liu
 */
public class DataSourceAutoMonitor implements BeanFactoryPostProcessor, PriorityOrdered {

    private static final Logger logger = LoggerLoader.getLogger(DataSourceAutoMonitor.class);

    private static final String ZEBRA_DATA_SOURCE_NAME = "com.dianping.zebra.jdbc.DPDataSource";

    private static int nameId = 0;

    private DefaultListableBeanFactory listableBeanFactory = null;

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        listableBeanFactory = (DefaultListableBeanFactory) beanFactory;
        String[] beanDefinitionNames = listableBeanFactory.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition) listableBeanFactory
                    .getBeanDefinition(beanDefinitionName);
            try {
                Class<?> beanClazz = beanDefinition.resolveBeanClass(ClassUtils.getDefaultClassLoader());
                if (beanClazz != null && DataSource.class.isAssignableFrom(beanClazz)
                        && (!GroupDataSource.class.isAssignableFrom(beanClazz))
                        && (!ShardDataSource.class.isAssignableFrom(beanClazz))) {
                    autoReplaceWithMonitorableDataSource(beanDefinitionName, beanDefinition, beanClazz);
                }
            } catch (ClassNotFoundException e) {
            }
        }
        if (logger.isInfoEnabled()) {
            logger.info("All dataSource is auto monitored by zebra ds monitor.");
        }
    }

    private void autoReplaceWithMonitorableDataSource(String beanName, BeanDefinition dataSourceDefinition,
            Class<?> dataSourceClazz) {

        if (isZebraDataSource(dataSourceClazz)) {
            if (!checkInnerDataSourceInZebra(beanName, dataSourceDefinition)) {
                return;
            }
        }

        listableBeanFactory.registerBeanDefinition(beanName,
                createMonitorableBeanDefinition(beanName, dataSourceDefinition));

        // zebra??inner datasource?nested bean??wrapper
        if (isZebraDataSource(dataSourceClazz)) {
            replaceInnerDataSourceInZebra(beanName, dataSourceDefinition);
        }
    }

    @SuppressWarnings("unchecked")
    private boolean checkInnerDataSourceInZebra(String beanName, BeanDefinition zebraDataSourceDefinition) {
        MutablePropertyValues propertyValues = zebraDataSourceDefinition.getPropertyValues();
        PropertyValue dataSourcePoolVal = propertyValues.getPropertyValue("dataSourcePool");

        if (dataSourcePoolVal == null) {
            if (logger.isWarnEnabled()) {
                logger.warn("Zebra dataSource's dataSourcePool property not found, maybe its name is modified, "
                        + "change the automonitor's implementation, otherwise some inner dataSource cannot be monitored.");
            }
            return true;
        }

        Map<TypedStringValue, Object> innerDSDefinitionMap = (Map<TypedStringValue, Object>) dataSourcePoolVal
                .getValue();
        for (Entry<TypedStringValue, Object> innerDSDefEntry : innerDSDefinitionMap.entrySet()) {
            Object innerDSDefVal = innerDSDefEntry.getValue();
            if (innerDSDefVal instanceof BeanDefinitionHolder) {
                BeanDefinitionHolder innerDSDefHolder = (BeanDefinitionHolder) innerDSDefVal;
                BeanDefinition innerDSDefinition = innerDSDefHolder.getBeanDefinition();
                if (GroupDataSource.class.getName().equals(innerDSDefinition.getBeanClassName())) {
                    return false;
                }
            }
        }

        return false;
    }

    @SuppressWarnings("unchecked")
    private void replaceInnerDataSourceInZebra(String beanName, BeanDefinition zebraDataSourceDefinition) {
        MutablePropertyValues propertyValues = zebraDataSourceDefinition.getPropertyValues();
        PropertyValue dataSourcePoolVal = propertyValues.getPropertyValue("dataSourcePool");

        if (dataSourcePoolVal == null) {
            if (logger.isWarnEnabled()) {
                logger.warn("Zebra dataSource's dataSourcePool property not found, maybe its name is modified, "
                        + "change the automonitor's implementation, otherwise some inner dataSource cannot be monitored.");
            }
            return;
        }

        Map<TypedStringValue, Object> innerDSDefinitionMap = (Map<TypedStringValue, Object>) dataSourcePoolVal
                .getValue();
        for (Entry<TypedStringValue, Object> innerDSDefEntry : innerDSDefinitionMap.entrySet()) {
            Object innerDSDefVal = innerDSDefEntry.getValue();
            if (innerDSDefVal instanceof BeanDefinitionHolder) {
                BeanDefinitionHolder innerDSDefHolder = (BeanDefinitionHolder) innerDSDefVal;
                BeanDefinition innerDSDefinition = innerDSDefHolder.getBeanDefinition();
                innerDSDefEntry.setValue(
                        new BeanDefinitionHolder(createMonitorableBeanDefinition(beanName, innerDSDefinition),
                                innerDSDefHolder.getBeanName(), innerDSDefHolder.getAliases()));
            }
        }
    }

    private BeanDefinition createMonitorableBeanDefinition(String beanName, BeanDefinition dataSourceDefinition) {
        if (MonitorableDataSource.class.getName().equals(dataSourceDefinition.getBeanClassName())
                || GroupDataSource.class.getName().equals(dataSourceDefinition.getBeanClassName())) {
            return dataSourceDefinition;
        }

        String newBeanName = String.format("%s-z%d", beanName, nameId++);

        listableBeanFactory.registerBeanDefinition(newBeanName, dataSourceDefinition);

        GenericBeanDefinition monitorableDataSourceDefinition = new GenericBeanDefinition();
        monitorableDataSourceDefinition.setBeanClass(MonitorableDataSource.class);
        monitorableDataSourceDefinition.getConstructorArgumentValues()
                .addGenericArgumentValue(new RuntimeBeanReference(newBeanName));
        return monitorableDataSourceDefinition;
    }

    private boolean isZebraDataSource(Class<?> dataSourceClazz) {
        return ZEBRA_DATA_SOURCE_NAME.equals(dataSourceClazz.getName());
    }

    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE - 1;
    }
}