动态数据源初始化的问题

package com.goupu.frame.datasources;

import java.sql.SQLException;

import javax.sql.DataSource;

import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.log4j.Logger;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.Environment;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.PlatformTransactionManager;

import com.alibaba.druid.pool.DruidDataSource;
import com.goupu.frame.initweb.BeanManager;


@Configuration
@PropertySource({"classpath:sysconfig/jdbc.properties"})
@Order(value=1) 
public class ReadAndWriteDataSourceConfig {
	
	private static final Logger logger = Logger.getLogger(ReadAndWriteDataSourceConfig.class);
	@Autowired
	private Environment env;//配置上下文
	@Bean(name="writeDatasource")
    @Primary
	public DruidDataSource writeDatasource() {
		DruidDataSource datasource=new DruidDataSource();
		String dbPrefix="write";
        String driverClass=env.getProperty(dbPrefix+".dataSource.driverClass");
        String jdbcUrl=env.getProperty(dbPrefix+".dataSource.jdbcUrl");
        String user=env.getProperty(dbPrefix+".dataSource.user");
        String password=env.getProperty(dbPrefix+".dataSource.password");
    	String initialSize=env.getProperty(dbPrefix+".dataSource.initialSize");
    	String maxActive=env.getProperty(dbPrefix+".dataSource.maxActive");
    	String maxIdle=env.getProperty(dbPrefix+".dataSource.maxIdle");
    	String minIdle=env.getProperty(dbPrefix+".dataSource.minIdle");
    	String maxWait=env.getProperty(dbPrefix+".dataSource.maxWait");
    	String removeAbandoned=env.getProperty(dbPrefix+".dataSource.removeAbandoned");
    	String removeAbandonedTimeout=env.getProperty(dbPrefix+".dataSource.removeAbandonedTimeout");
    	String timeBetweenEvictionRunsMillis=env.getProperty(dbPrefix+".dataSource.timeBetweenEvictionRunsMillis");
    	String minEvictableIdleTimeMillis=env.getProperty(dbPrefix+".dataSource.minEvictableIdleTimeMillis");
    	String validationQuery=env.getProperty(dbPrefix+".dataSource.validationQuery");
    	String testWhileIdle=env.getProperty(dbPrefix+".dataSource.testWhileIdle");
    	String testOnBorrow=env.getProperty(dbPrefix+".dataSource.testOnBorrow");
    	String testOnReturn=env.getProperty(dbPrefix+".dataSource.testOnReturn");
    	String poolPreparedStatements=env.getProperty(dbPrefix+".dataSource.poolPreparedStatements");
    	String maxPoolPreparedStatementPerConnectionSize=env.getProperty(dbPrefix+".dataSource.maxPoolPreparedStatementPerConnectionSize");
    	String filters=env.getProperty(dbPrefix+".dataSource.filters");
    	System.out.println("-------------jdbcUrl=="+jdbcUrl);
        datasource.setUrl(jdbcUrl);
        datasource.setUsername(user);
        datasource.setPassword(password);
        datasource.setDriverClassName(driverClass);
        datasource.setInitialSize(Integer.parseInt(initialSize));
        datasource.setMinIdle(Integer.parseInt(minIdle));
        datasource.setRemoveAbandoned(Boolean.getBoolean(removeAbandoned));
        datasource.setRemoveAbandonedTimeout(Integer.parseInt(removeAbandonedTimeout));
        
        datasource.setMaxActive(Integer.parseInt(maxActive));
        datasource.setMaxWait(Integer.parseInt(maxWait));
        datasource.setTimeBetweenEvictionRunsMillis(Integer.parseInt(timeBetweenEvictionRunsMillis));
        datasource.setMinEvictableIdleTimeMillis(Integer.parseInt(minEvictableIdleTimeMillis));
        datasource.setValidationQuery(validationQuery);
        datasource.setTestWhileIdle(Boolean.getBoolean(testWhileIdle));
        datasource.setTestOnBorrow(Boolean.getBoolean(testOnBorrow));
        datasource.setTestOnReturn(Boolean.getBoolean(testOnReturn));
        datasource.setPoolPreparedStatements(Boolean.getBoolean(poolPreparedStatements));
        datasource.setMaxPoolPreparedStatementPerConnectionSize(Integer.parseInt(maxPoolPreparedStatementPerConnectionSize));
        try {
        	datasource.setFilters(filters);
        }catch(Exception e) {
        	logger.error("-------------初始化写库失败");
        }
        logger.error("-------------初始化写库成功");
		return datasource;
	}
	
	@Bean(name = "readDataSource") 
    public DataSource readDataSource() {//从数据源,查询操作
    	DruidDataSource datasource = new DruidDataSource();
    	try {
	        String dbPrefix="read";
	        String driverClass=env.getProperty(dbPrefix+".dataSource.driverClass");
	        String jdbcUrl=env.getProperty(dbPrefix+".dataSource.jdbcUrl");
	        String user=env.getProperty(dbPrefix+".dataSource.user");
	        String password=env.getProperty(dbPrefix+".dataSource.password");
	    	String initialSize=env.getProperty(dbPrefix+".dataSource.initialSize");
	    	String maxActive=env.getProperty(dbPrefix+".dataSource.maxActive");
	    	String maxIdle=env.getProperty(dbPrefix+".dataSource.maxIdle");
	    	String minIdle=env.getProperty(dbPrefix+".dataSource.minIdle");
	    	String maxWait=env.getProperty(dbPrefix+".dataSource.maxWait");
	    	String removeAbandoned=env.getProperty(dbPrefix+".dataSource.removeAbandoned");
	    	String removeAbandonedTimeout=env.getProperty(dbPrefix+".dataSource.removeAbandonedTimeout");
	    	String timeBetweenEvictionRunsMillis=env.getProperty(dbPrefix+".dataSource.timeBetweenEvictionRunsMillis");
	    	String minEvictableIdleTimeMillis=env.getProperty(dbPrefix+".dataSource.minEvictableIdleTimeMillis");
	    	String validationQuery=env.getProperty(dbPrefix+".dataSource.validationQuery");
	    	String testWhileIdle=env.getProperty(dbPrefix+".dataSource.testWhileIdle");
	    	String testOnBorrow=env.getProperty(dbPrefix+".dataSource.testOnBorrow");
	    	String testOnReturn=env.getProperty(dbPrefix+".dataSource.testOnReturn");
	    	String poolPreparedStatements=env.getProperty(dbPrefix+".dataSource.poolPreparedStatements");
	    	String maxPoolPreparedStatementPerConnectionSize=env.getProperty(dbPrefix+".dataSource.maxPoolPreparedStatementPerConnectionSize");
	    	String filters=env.getProperty(dbPrefix+".dataSource.filters");
	    	
	        datasource.setUrl(jdbcUrl);
	        datasource.setUsername(user);
	        datasource.setPassword(password);
	        datasource.setDriverClassName(driverClass);
	        datasource.setInitialSize(Integer.parseInt(initialSize));
	        datasource.setMinIdle(Integer.parseInt(minIdle));
	        //datasource.setMaxIdle(Integer.parseInt(maxIdle));
	        datasource.setRemoveAbandoned(Boolean.getBoolean(removeAbandoned));
	        datasource.setRemoveAbandonedTimeout(Integer.parseInt(removeAbandonedTimeout));
	        
	        datasource.setMaxActive(Integer.parseInt(maxActive));
	        datasource.setMaxWait(Integer.parseInt(maxWait));
	        datasource.setTimeBetweenEvictionRunsMillis(Integer.parseInt(timeBetweenEvictionRunsMillis));
	        datasource.setMinEvictableIdleTimeMillis(Integer.parseInt(minEvictableIdleTimeMillis));
	        datasource.setValidationQuery(validationQuery);
	        datasource.setTestWhileIdle(Boolean.getBoolean(testWhileIdle));
	        datasource.setTestOnBorrow(Boolean.getBoolean(testOnBorrow));
	        datasource.setTestOnReturn(Boolean.getBoolean(testOnReturn));
	        datasource.setPoolPreparedStatements(Boolean.getBoolean(poolPreparedStatements));
	        datasource.setMaxPoolPreparedStatementPerConnectionSize(Integer.parseInt(maxPoolPreparedStatementPerConnectionSize));
	        
            datasource.setFilters(filters);
            //datasource.setConnectionProperties(connectionProperties);
        } catch (SQLException e) {
        	logger.error("-------------初始化读库失败");
        }
    	logger.error("-------------初始化读库成功");
        return datasource;
    }
}

package com.goupu.frame.datasources;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

@Configuration
@Qualifier("dynamicDataSource") 
@Order(value=2)  
public class DynamicDataSource extends AbstractRoutingDataSource {
	
	private AtomicInteger count = new AtomicInteger(0);
	private int readSize=0;
	@Autowired
	@Qualifier("writeDataSource")
    private Object writeDataSource; //写数据源
	@Autowired
	@Qualifier("readDataSource")
    private Object readDataSource; //读数据源
    @Override
    public void afterPropertiesSet() {
        if (this.writeDataSource == null) {
            throw new IllegalArgumentException("Property 'writeDataSource' is required");
        }
        setDefaultTargetDataSource(writeDataSource);
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(DynamicDataSourceGlobal.WRITE.name(), writeDataSource);
        if(readDataSource != null) {
            targetDataSources.put(DynamicDataSourceGlobal.READ.name()+"1", readDataSource);
        }
        
         readSize =targetDataSources.size()-1;
        setTargetDataSources(targetDataSources);
        super.afterPropertiesSet();
    }

    @Override
    protected Object determineCurrentLookupKey() {

        String typeKey  = DynamicDataSourceHolder.getDataSource();

        if(typeKey == null){
    			throw new NullPointerException("数据库路由时,决定使用哪个数据库源类型不能为空...");
    	}
        if (typeKey.equals(DynamicDataSourceGlobal.WRITE.name())){
        	//System.err.println("使用写数据库写入");
            return DynamicDataSourceGlobal.WRITE.name();
        }else{
        	//System.err.println("使用读数据库查询");
        }
        //System.err.println("使用数据库read");
        return DynamicDataSourceGlobal.READ.name()+1;
    }
    
}

报错信息:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'dynamicDataSource': Unsatisfied dependency expressed through field 'writeDataSource'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.lang.Object' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier("writeDataSource")}

有人能帮忙解答一下吗?

解决方案如下:

  1. service接口实现类上有没有加@Service注解,注解是不是引用的spring的类?不要导错包

  2. 接口有没有写实现类,实现类是实现的对应接口么?比如CategoryServiceImpl implementsCategoryDAO 一不小心根据自动提示,本来应该实现CategoryService,结果实现了CategoryDAO

  3. 有没有扫描Service所在的包

<context:component-scan base-package="com.ssm.blog.*">  
    <!-- 制定扫包规则 ,不扫描@Controller注解的JAVA类 -->  
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>  
</context:component-scan>

4)确保代码无误后,再看看包是否下载完整

5)查看注入是否正确
————————————————
原文链接:org.springframework.beans.factory.UnsatisfiedDependencyException:解决方案_武大大不吃糖的博客-CSDN博客

1 个赞

谢谢你的答复,但是看了还是没看懂是什么问题,这些代码从另外一个项目拷贝过来的,完全没有改的,另外一个项目是可以跑的,我现在是学习拷贝出来模拟一下的。还有没有其他建议呢