Spring Data Redis不初始化RestTemplate

时间:2017-11-09 22:31:49

标签: spring spring-boot redis javabeans

我已将两个Spring Data模块集成到我的应用程序中:Spring Data MongoDB和Spring Data Redis。

虽然Spring Data MongoDB模块就像魅力一样工作,但由于与RestTemplate bean连接相关的问题,我正在努力使用Spring Data Redis,这是与Redis交互所必需的。

一旦Spring Boot应用程序启动,我最终会遇到以下错误:

  

***************************申请失败

           

说明

     

构造函数的参数0   com.github.wjoz.talkative.messageService.repository.redis.impl.RedisMessageRepositoryImpl   需要一个类型的bean   'org.springframework.data.redis.core.RedisTemplate'不可能   找到。      - 未加载'RedisAutoConfiguration.RedisConfiguration'中的Bean方法'redisTemplate',因为   @ConditionalOnMissingBean(名称:redisTemplate; SearchStrategy:all)   找到豆'redisTemplate'

     

动作:

     

考虑重新审视上述条件或定义类型的bean   你的'org.springframework.data.redis.core.RedisTemplate'   配置。

Spring说bean无法实例化,但是当我在redisTemplate()上调试时,bean在BeanFactory(IoC Container)中创建并实例化,因为执行停止了。

我有两个Spring Data模块,因此Spring Data正在进入严格的存储库配置模式,如日志中所述:

  

找到多个Spring Data模块,进入严格的存储库   配置模式!

对于Spring Data Redis我既没有使用Repository也没有使用CrudRepository接口,相反,由于这里提到的问题,我用普通的@Repository注释实现了它: Repositories - Multiple Modules

我认为Spring Boot启动器中的版本冲突可能存在问题。但我无法弄清楚。

提前致谢。

的pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.github.wjoz</groupId>
<artifactId>talkative-message-service</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>

<name>talkative-message-service</name>

<properties>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <spring.version>5.0.1.RELEASE</spring.version>
    <spring.security.jwt.version>1.0.7.RELEASE</spring.security.jwt.version>
    <spring.cloud.starter.version>1.2.3.RELEASE</spring.cloud.starter.version>
    <spring.cloud.eureka.server.version>1.3.4.RELEASE</spring.cloud.eureka.server.version>
    <oauth.version>2.0.12.RELEASE</oauth.version>
    <modelmapper.version>0.7.7</modelmapper.version>
    <junit.version>4.12</junit.version>
    <h2.version>1.4.193</h2.version>
    <log4j2.version>2.8.1</log4j2.version>
    <jackson.version>2.8.7</jackson.version>
    <apachecommons.version>2.5</apachecommons.version>
</properties>

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.8.RELEASE</version>
</parent>

<dependencies>
     <!-- Setup Spring Boot -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>

    <!-- Setup Spring MVC & REST, use Embedded Tomcat -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
    </dependency>

    <!-- Spring Cloud starter -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter</artifactId>
        <version>${spring.cloud.starter.version}</version>
    </dependency>

    <!-- Spring Data Redis -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>

    <!-- Spring Data MongoDB -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-mongodb</artifactId>
    </dependency>

    <!-- Spring Boot Starter Security -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>

    <!-- Spring Boot Starter Security OAuth 2 -->
    <dependency>
        <groupId>org.springframework.security.oauth</groupId>
        <artifactId>spring-security-oauth2</artifactId>
        <version>${oauth.version}</version>
    </dependency>

    <!-- Spring Test Framework -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <!-- Spring Security module for JSON Web Token support -->
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-jwt</artifactId>
        <version>${spring.security.jwt.version}</version>
    </dependency>

    <!-- Eureka for service registration -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-eureka-server</artifactId>
        <version>${spring.cloud.eureka.server.version}</version>
    </dependency>

    <!-- ModelMapper for DTO/Domain object conversion -->
    <dependency>
        <groupId>org.modelmapper</groupId>
        <artifactId>modelmapper</artifactId>
        <version>${modelmapper.version}</version>
    </dependency>

    <!-- JUnit -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>${junit.version}</version>
        <scope>test</scope>
    </dependency>

    <!-- Embedded Redis for integration tests -->
    <dependency>
        <groupId>it.ozimov</groupId>
        <artifactId>embedded-redis</artifactId>
        <version>0.7.1</version>
        <scope>test</scope>
    </dependency>

    <!-- Spring Boot Hot Swap -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <optional>true</optional>
    </dependency>

    <!-- Log4j 2 API -->
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-api</artifactId>
        <version>${log4j2.version}</version>
    </dependency>

    <!-- Log4j 2 Core -->
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>${log4j2.version}</version>
    </dependency>

    <!-- Log4j 2 YAML support -->
    <dependency>
        <groupId>com.fasterxml.jackson.dataformat</groupId>
        <artifactId>jackson-dataformat-yaml</artifactId>
        <version>${jackson.version}</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>${jackson.version}</version>
    </dependency>

    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>${apachecommons.version}</version>
    </dependency>

</dependencies>

<build>
    <resources>
        <!--<resource>-->
        <!--<directory>src/main/resources</directory>-->
        <!--<filtering>true</filtering>-->
        <!--<excludes>-->
        <!--<exclude>*.jks</exclude>-->
        <!--</excludes>-->
        <!--</resource>-->
    </resources>
    <plugins>
        <!-- Package as an executable jar -->
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <addResources>true</addResources>
            </configuration>
        </plugin>
    </plugins>
</build>

BaseAppConfig - 配置类

    @Configuration
    @Profile({ApplicationProfiles.DEVELOPMENT, ApplicationProfiles.PRODUCTION})
    @EnableMongoRepositories(basePackages = Packages.MONGO_REPOSITORY)
    public class BaseAppConfig {

        /**
         * Configures the Java client for Redis.
         * @return the Java Redis client object
         */
        @Bean
        public JedisConnectionFactory jedisConnectionFactory() {
            return new JedisConnectionFactory();
        }

        /**
         * Provides the central class of the Redis module for Redis interactions.
         * @return the Redis interaction class
         */
        @Bean
        public RedisTemplate<String, Object> redisTemplate() {
            RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
            redisTemplate.setConnectionFactory(jedisConnectionFactory());
            return redisTemplate;
        }
    }

MongoMessageRepository

    public interface MongoMessageRepository extends CrudRepository<Message, String> {

    }

RedisMessageRepositoryImpl - 我尝试自动装配RestTemplate的位置

@Repository
public class RedisMessageRepositoryImpl implements RedisMessageRepository {

    private static final String KEY = "Message";
    private final RedisTemplate<String, Message> redisTemplate;
    private HashOperations<String, String, Message> hashOperations;

    @Inject
    private RedisMessageRepositoryImpl(RedisTemplate<String, Message> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Override
    public void save(Message message) {
        hashOperations.put(KEY, message.getId(), message);
    }
}

更新: 我添加了主要的MessageServer类,它非常简单:

@EnableDiscoveryClient
@SpringBootApplication(scanBasePackages = Packages.COMPONENT_ROOT)
@EnableFeignClients
public class MessageServer {
    public static void main(String[] args) {
        SpringApplication.run(MessageServer.class, args);
    }
}

1 个答案:

答案 0 :(得分:1)

好的,我已经设法弄清楚问题的原因是什么。 bean在IoC容器中实例化,但是在尝试在RedisMessageRepositoryImpl中自动连接它时出现了问题,因为我犯了两个愚蠢的错误:

首先,我在

中意外使用了私有修饰符而不是公开
//  this is mock 'service'
const service = {
    call: (data) => {
        console.log('service is called with "' + data + '"');
        //  returning Promise because 'then' is used in consuming code
        return new Promise((resolve, reject) => {
            setTimeout(() => resolve({ data: '"This is result of call to service"' }), 1000);
        })
    }
}

//  this is mock 'service2'
const service2 = {
    //  no Promise here because there is no 'then' in consuming code
    call: (data, callback) => {
        console.log('service2 is called with ' + data);
        //setTimeout(() => callback('"This is result of call to service2 with ' + data + '"'), 1000);   //  this would be success scenario
        setTimeout(() => callback(null, "service 2 failed"), 2000);     //  this is a failure scenario
    }
}

//  now call the services
service.call('data').then(result => {
    console.log("service completed with " + JSON.stringify(result));
    var err = '';
    service2.call(result.data, (result2, error) => {
        if (error) {
            console.log('service2 failed with message "' + error + '"');
            err = error;
        }   
    })

    //  we're setting timeout big enough for service2 to complete to give it a chance to chang err variable before it's written to console
    setTimeout(() => {
            console.log('ultimate value of "err" variable is "' + err + '"');
        },
        5000        //  you may try it with 1000 delay to see unchanged value
    )
})

因此即使用@Repository标记了bean本身也无法实例化。

我不得不删除RedisTemplate的通用声明:

 @Inject
    private RedisMessageRepositoryImpl(RedisTemplate<String, Message> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

private final RedisTemplate<String, Message> redisTemplate;

通过这种方式,bean现在自动装配,没有任何问题,也可以在IntelliJ中找到,一切都很好。