spring 应用程序上下文中某些bean的依赖关系在Sping Boot 中形成了一个循环

xvw2m8pv  于 11个月前  发布在  Spring
关注(0)|答案(1)|浏览(108)

我使用spring Boot 创建了一个应用程序,它有4种数据库类型:h2,mongodb,redis和neo4j。
我已经实现了h2和mongodb代码。
我将使用aggregatedRating实体示例。
我的逻辑是application.properties中的一个uri,一个包含端点、服务接口、服务实现、AggregatedRatingRepository、AggregatedRatingRepositoryMongo和AggregatedRatingRepositoryImpl的控制器。我还有一个mongoConfig,用于配置Mongo模板。
代码如下:

MongoConfig

package com.isep.acme.config;

import com.isep.acme.model.mongoDomain.*;
import com.isep.acme.repositories.*;
import com.isep.acme.repositories.mongo.*;
import com.mongodb.MongoClientSettings;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration;
import org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Profile;
import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;

import java.lang.reflect.Constructor;
import java.time.LocalDate;
import java.util.Collections;

@Profile("mongo")
@Configuration
@EnableMongoRepositories(basePackages = "com.isep.acme.repositories.mongo")
@SpringBootApplication(exclude = {
        DataSourceAutoConfiguration.class,
        DataSourceTransactionManagerAutoConfiguration.class,
        HibernateJpaAutoConfiguration.class
})
public class MongoConfig {

    @Value("${spring.data.mongodb.uri}")
    private String mongoPrivateUri;

    @Bean
    public MongoTemplate mongoTemplate() {
        return new MongoTemplate(new SimpleMongoClientDatabaseFactory(mongoPrivateUri));
    }

}

字符串

AggregatedRatingService

package com.isep.acme.services;

import com.isep.acme.model.AggregatedRating;

public interface AggregatedRatingService {

    AggregatedRating save(String sku);
}

AggregatedRatingServiceImpl

package com.isep.acme.services;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.isep.acme.model.AggregatedRating;
import com.isep.acme.model.Product;
import com.isep.acme.repositories.AggregatedRatingRepository;
import com.isep.acme.repositories.ProductRepository;

import java.util.Optional;

@Service
public class AggregatedRatingServiceImpl implements AggregatedRatingService{

    @Autowired
    AggregatedRatingRepository arRepository;

    @Autowired
    private ProductRepository pRepository;

    @Autowired
    ReviewService rService;

    @Autowired
    ProductService productService;

    @Override
    public AggregatedRating save( String sku ) {

        Optional<Product> product = pRepository.findBySku( sku );

        if (product.isEmpty()){
            return null;
        }

        Double average = rService.getWeightedAverage(product.get());

        Optional<AggregatedRating> r = arRepository.findByProductId(product.get());
        AggregatedRating aggregateF;

        if(r.isPresent()) {
            r.get().setAverage( average );
            aggregateF = (AggregatedRating) arRepository.save(r.get());
        }
        else {
            AggregatedRating f = new AggregatedRating(average, product.get());
            aggregateF = (AggregatedRating) arRepository.save(f);
        }

        return aggregateF;
    }

}

AggregatedRatingRepository

package com.isep.acme.repositories;

import com.isep.acme.model.Product;
import org.springframework.data.repository.CrudRepository;

import java.util.Optional;

public interface AggregatedRatingRepository<T,L> extends CrudRepository<T, Long>{

    Optional<T> findByProductId(Product product);

}

AggregatedRatingMongoRepository

package com.isep.acme.repositories.mongo;

import com.isep.acme.model.Product;
import com.isep.acme.model.mongoDomain.AggregatedRatingMongo;
import com.isep.acme.repositories.AggregatedRatingRepository;
import org.springframework.context.annotation.Profile;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.mongodb.repository.Query;

import java.util.Optional;

@Profile("mongo")
public interface AggregatedRatingMongoRepository extends AggregatedRatingRepository<AggregatedRatingMongo,Long>, MongoRepository<AggregatedRatingMongo, Long> {

    @Query("{'product.sku':?0}")
    Optional<AggregatedRatingMongo> findByProductId(Product product);
}

AggregatedRatingMongoRepositoryImpl

package com.isep.acme.repositories.mongo.impl;

import com.isep.acme.model.Product;
import com.isep.acme.model.mongoDomain.AggregatedRatingMongo;
import com.isep.acme.repositories.mongo.AggregatedRatingMongoRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Profile;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.repository.query.FluentQuery;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Optional;
import java.util.function.Function;

@Repository
@Profile("mongo")
@Primary
public class AggregatedRatingMongoRepositoryImpl implements AggregatedRatingMongoRepository {

    private final AggregatedRatingMongoRepository repo;
    @Autowired
    public AggregatedRatingMongoRepositoryImpl(@Qualifier("aggregatedRatingMongoRepository") AggregatedRatingMongoRepository aggregatedRatingMongoRepository) {
        this.repo = aggregatedRatingMongoRepository;
    }

 ... all the methods implemented by default from mongo (save, saveall, getbyid, etc)


我的application.properties看起来像这样:

# swagger-ui custom path
springdoc.api-docs.enabled=true
springdoc.api-docs.path=/api-docs
springdoc.swagger-ui.path=/swagger-ui

## JWT
jwt.private.key=classpath:rsa.private.key
jwt.public.key=classpath:rsa.public.key

spring.datasource.url=jdbc:h2:file:./data/acme;MV_STORE=FALSE;AUTO_SERVER=true;
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=gg
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
# access h2 console at http://localhost:8080/h2-console  

spring.jpa.hibernate.ddl-auto=create-drop

## MULTIPART (MultipartProperties)
# Enable multipart uploads
spring.servlet.multipart.enabled=true
# Threshold after which files are written to disk.
spring.servlet.multipart.file-size-threshold=2KB
# Max file size.
spring.servlet.multipart.max-file-size=200MB
# Max Request Size
spring.servlet.multipart.max-request-size=215MB

file.upload-dir=DEV/FileUploads

## Logging
logging.level.com.example.demo=DEBUG
#logging.level.org.springframework=DEBUG

## Profiles
spring.profiles.active=bootstrap,mongo

##Set sku method
sku.creation.method=method1
spring.main.allow-circular-references=true
spring.main.allow-bean-definition-overriding=true
spring.data.mongodb.uri=mongodb+srv://myinfo.mongodb.net/?retryWrites=true&w=majority
spring.data.mongodb.auto-index-creation=true

错误

这里的问题是,我面临这个错误:

2023-11-04 21:14:07.539 ERROR 13436 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

The dependencies of some of the beans in the application context form a cycle:

   aggregatedRatingController (field com.isep.acme.services.AggregatedRatingService com.isep.acme.controllers.AggregatedRatingController.aService)
      ↓
   aggregatedRatingServiceImpl (field com.isep.acme.repositories.AggregatedRatingRepository com.isep.acme.services.AggregatedRatingServiceImpl.arRepository)
┌─────┐
|  aggregatedRatingMongoRepositoryImpl defined in file [C:mylocation\acme\repositories\mongo\impl\AggregatedRatingMongoRepositoryImpl.class]
└─────┘

8xiog9wr

8xiog9wr1#

对于初学者来说,你不能将一个引用连接到AggregatedRatingMongoRepository并在同一个类中实现它。这就是给你循环引用运行时错误的原因。
还有,在AggregatedRatingMongoRepositoryImpl中实现自己版本的所有CrudRepository方法对我来说似乎非常奇怪,并且有点代码味道。考虑到实现CrudRepository的全部目的是免费提供所有CRUD操作,而不需要自己实现它们,这似乎非常奇怪。如果你只是在AggregatedRatingRepository中连接而不实现它,你就不必这样做。当你在继承链的更下游实现AggregatedRatingRepository需要你自己实现所有的东西,这是应该避免的。

相关问题