循环表单Bean的应用程序问题

时间:2018-11-18 14:01:30

标签: java spring

我的应用程序不会以以下消息开头:

应用程序上下文中某些bean的依赖性形成一个循环:

bookController    ↓

bookServiceImpl

┌─────┐

bookCommandToBook

↑↓
authorCommandToAuthor

└─────┘

BookController

package pl.springwebapp.webapp.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import pl.springwebapp.webapp.command.BookCommand;
import pl.springwebapp.webapp.service.BookService;

@Slf4j
@Controller
public class BookController {
private BookService bookService;

public BookController(BookService bookService) {
    this.bookService = bookService;
}

@RequestMapping("/book/show/{id}")
public String showDescriptionById(@PathVariable long id, Model model){
    model.addAttribute("book",bookService.findByID(id));
    return "/book/show";
}

@RequestMapping("book/new")
public String newBook(Model model){
    model.addAttribute("book", new BookCommand());

    return  "book/bookform";
}

@PostMapping
@RequestMapping(name = "book")
public String saveOrUpdate(@ModelAttribute BookCommand bookCommand){
    bookService.saveBookCommand(bookCommand);
    return "redirect:/index";
}
}

BookServiceImpl

package pl.springwebapp.webapp.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import pl.springwebapp.webapp.command.BookCommand;
import pl.springwebapp.webapp.converter.BookCommandToBook;
import pl.springwebapp.webapp.converter.BookToBookCommand;
import pl.springwebapp.webapp.model.Book;
import pl.springwebapp.webapp.repository.BookRepository;

import javax.transaction.Transactional;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;

@Slf4j
@Service
public class BookServiceImpl implements BookService {

private BookRepository bookRepository;
private BookCommandToBook  bookCommandToBook;
private BookToBookCommand bookToBookCommand;

public BookServiceImpl(BookRepository bookRepository, BookCommandToBook bookCommandToBook, BookToBookCommand bookToBookCommand) {
    this.bookRepository = bookRepository;
    this.bookCommandToBook = bookCommandToBook;
    this.bookToBookCommand = bookToBookCommand;
}

@Override
public Set<Book> getBooks(){
    Set<Book> bookSet = new HashSet<>();
    bookRepository.findAll().iterator().forEachRemaining(bookSet::add);
    return bookSet;
}

@Override
public Book findByID(long id) {
    Optional<Book> optionalBook = bookRepository.findById((id));
    if(!optionalBook.isPresent()){
        throw new RuntimeException("Book not found");
    }
    return optionalBook.get();
}

@Transactional
@Override
public BookCommand saveBookCommand(BookCommand bookCommand) {
    Book receivedBook = bookCommandToBook.convert(bookCommand);
    Book savedBook = bookRepository.save(receivedBook);
    return bookToBookCommand.convert(savedBook);
}
}

BookCommandToBook

package pl.springwebapp.webapp.converter;

import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
import pl.springwebapp.webapp.command.BookCommand;
import pl.springwebapp.webapp.model.Book;


@Component
public class BookCommandToBook implements Converter<BookCommand, Book> {

private AuthorCommandToAuthor authorConverter;
private CategoryCommandToCategory categoryConverter;

public BookCommandToBook(AuthorCommandToAuthor authorConverter, CategoryCommandToCategory categoryConverter) {
    this.authorConverter = authorConverter;
    this.categoryConverter = categoryConverter;
}


@Override
public Book convert(BookCommand bookCommand) {
    Book book = new Book();
    book.setId(bookCommand.getId());
    book.setTitle(bookCommand.getTitle());
    book.setIsbn(bookCommand.getIsbn());
    book.setDescription(bookCommand.getDescription());
    book.setAuthor(authorConverter.convert(bookCommand.getAuthor()));

   if(bookCommand.getCategorySet() != null && bookCommand.getCategorySet().size() > 0 ){
        bookCommand.getCategorySet().forEach(categoryCommand -> book.getCategories().add(categoryConverter.convert(categoryCommand)));
    }

    return book;
}
}

AuthorCommandToAuthor

package pl.springwebapp.webapp.converter;

import lombok.Synchronized;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
import pl.springwebapp.webapp.command.AuthorCommand;
import pl.springwebapp.webapp.model.Author;


@Component
public class AuthorCommandToAuthor implements Converter<AuthorCommand, Author> {

private BookCommandToBook bookConverter;

public AuthorCommandToAuthor(BookCommandToBook bookConverter) {
    this.bookConverter = bookConverter;
}

@Synchronized
@Override
   public Author convert(AuthorCommand authorCommand) {
    if(authorCommand==null){
        return null;
    }
    Author author = new Author();
    author.setId(authorCommand.getId());
    author.setName(authorCommand.getName());
    author.setLastName(authorCommand.getLastName());

    if(authorCommand.getBookCommandSet() != null && authorCommand.getBookCommandSet().size() > 0){
        authorCommand.getBookCommandSet()
                .forEach(bookCommand -> author.getBooks().add(bookConverter.convert(bookCommand)));
    }

    return author;
}
}

AuthorCommand

@Setter
@Getter
@NoArgsConstructor
public class AuthorCommand {
private long id;
private String name;
private String lastName;
private Set<BookCommand> bookCommandSet = new HashSet<>();
}

BookCommand

@Setter
@Getter
@NoArgsConstructor
public class BookCommand {
private long id;
private String title;
private String isbn;
private String description;
private Set<CategoryCommand> categorySet = new HashSet<>();
private AuthorCommand author;
}

您能帮我解决这个问题吗?

1 个答案:

答案 0 :(得分:0)

您的应用程序上下文中有一个循环。这意味着一个bean依赖于另一个,反之亦然。 Spring将无法创建那些bean,因为始终必须首先创建一个bean。更具体地说,AuthorCommandToAuthor需要BookCommandToBook,而BookCommandToBook需要AuthorCommandToAuthor

要解决您的问题,请将共享代码重构为一个重要的组件,并将其注入两个依赖项中。这样可以消除周期。