Spring boot构造函数Autowired Exception

时间:2016-05-09 13:25:19

标签: spring constructor spring-boot autowired

我的春季启动应用程序中有这些类(spring hibernate / data / jpa / web):

pkg实体:

public interface Base {
// getter/setter methods
}

@MappedSuperclass
public abstract class AbsBase implements Base {
// common fields & getter/setter methods
}

@Entity(name = "Config")
@Table(name = "config")
public class Config extends AbsBase implements Base, Serializable {
  //additional fields & getter/setter methods
}

pkg存储库:

@NoRepositoryBean
public interface BaseRepository<T extends Base> extends JpaRepository<T, Integer> {}

@Repository
public interface ConfigRepository extends BaseRepository<Config> {
//Queries
}

pkg服务:

@Transactional
public interface BaseService<T extends Base> {

    @Transactional  void add(T obj);
    @Transactional  void edit(T obj);
    //Etc..
}

public abstract class AbsBaseService<T extends Base> implements BaseService<T> {

    private BaseRepository<T> repository;

    public AbsBaseService(BaseRepository<T> repository) {
        super();
        this.repository = repository;
    }

    @Override   public void add(T obj) { repository.save(obj); }
    @Override   public void edit(T obj) { repository.save(obj); }
    // Etc
}

@Service
public class ConfigService extends AbsBaseService<Config> implements BaseService<Config> {

    private ConfigRepository repository;

    @Autowired
    public ConfigService(ConfigRepository repository) {
        super(repository);
        this.repository = repository;
    }
    // Etc.
}

如果我不创建任何控制器全部工作,但如果我创建一个控制器:

pkg控制器:

public interface BaseController<T extends Base> { // methods }

public abstract class AbsBaseController<T extends Base> implements BaseController<T> {

    private BaseService<T> service;

    public AbsBaseController(BaseService<T> service) {
        this.service = service;
    }

@Override
@RequestMapping(value = "/Add", method = RequestMethod.POST)
public String addAction(@ModelAttribute("entity") T entity, BindingResult result, Model model,
        final RedirectAttributes redirectAttributes) {

    service.add(entity, result);
    if (result.hasErrors()) {
        return addUrl;
    }
}

@Controller
public class ConfigController extends AbsBaseController<Config> implements BaseController<Config> {

    private ConfigService configService;

    @Autowired
    public ConfigController(ConfigService configService) {
        super(configService);
        this.configService = configService;
    }
}

我收到此错误(ConfigController中的错误自动连接ConfigService):

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'configControllerImpl' defined in file [C:\workspace-sts\prueba_boot_thymeleaf\target\classes\prueba\controller\config\ConfigControllerImpl.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [prueba.service.config.ConfigServiceImpl]: No qualifying bean of type [prueba.service.config.ConfigServiceImpl] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [prueba.service.config.ConfigServiceImpl] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:185) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1143) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1046) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839) ~[spring-context-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538) ~[spring-context-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118) ~[spring-boot-1.3.3.RELEASE.jar:1.3.3.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:766) [spring-boot-1.3.3.RELEASE.jar:1.3.3.RELEASE]
    at org.springframework.boot.SpringApplication.createAndRefreshContext(SpringApplication.java:361) [spring-boot-1.3.3.RELEASE.jar:1.3.3.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) [spring-boot-1.3.3.RELEASE.jar:1.3.3.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1191) [spring-boot-1.3.3.RELEASE.jar:1.3.3.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1180) [spring-boot-1.3.3.RELEASE.jar:1.3.3.RELEASE]
    at prueba.BootThymeleafApplication.main(BootThymeleafApplication.java:12) [classes/:na]
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [prueba.service.config.ConfigServiceImpl] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1373) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1119) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1014) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:813) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    ... 19 common frames omitted

第一个问题是: 我已经注释了@Transaction BaseService接口及其方法。这是对的吗?更好的AbsBaseService类?

我看到configService构造函数在Exception之前执行。 为什么不自动连接?

更新

我需要构造函数@Autowired,因为我在abstract / superclass泛型服务/控制器中实现了常用方法。

继承树: AbsBaseXXXX - &gt; AbsBaseCodeNameXXXX - &gt; AbsBaseCodeNamePeriodXXXX

Config从AbsBase扩展并实现Base。     ConfigService从AbsBaseService&lt;&gt;扩展而来并实现BaseService&lt;&gt; (使用ConfigRepository)     ConfigController从AbsBaseController延伸&lt;&gt;并实现BaseController&lt;&gt; (使用ConfigService)

我有一个通用方法实现的通用抽象类: 实体接口:     Base,BaseCodeName,BaseCodeNamePeriod ....

  • 抽象通用实体类: AbsBase,AbsBaseCodeName,AbsBaseCodeNamePeriod ....

  • 通用接口: BaseRepository,BaseCodeNameRepository,BaseCodeNamePeriodRepository,...

  • 抽象通用服务(他们需要相应的通用存储库): AbsBaseService,AbsBaseCodeNameService,AbsBaseCodeNamePeriodService,...

  • 抽象通用控制器(他们需要相应的通用服务): AbsBaseController等......

3 个答案:

答案 0 :(得分:0)

首先,大多数代码都可以简化,至少可以测试它是否运行良好:

@Transactional
public interface BaseService<T extends Base> {

    void add(T obj); // No need to repeat @Transactional here, unless you want to override default behaviour (says, read_only, for instance)
    void edit(T obj);
    //Etc..
}

// Not much use of an Abstract class here, all methods are exposed in the interface already

@Service
public class ConfigService implements BaseService<Config> {

    // Autowire the field directly. Constructor not needed anymore in this case
    @Autowired
    private ConfigRepository repository;
    // Etc.
}

控制器将遵循与服务相同的准则。

现在应该可以正常工作了。如果没有,您需要使用完整堆栈跟踪(或至少最后一个caused by块更新您的问题,这是一个非常有意义的块。)

答案 1 :(得分:0)

解决方案:

创建服务界面: IConfigService扩展了BaseService

更改服务类: ConfigService扩展AbsBaseService实现IConfigService

在ControllerConfig中替换IConfigService的ConfigService

如果我使用界面工作,但如果我使用类不工作。我不明白为什么但它有效。

答案 2 :(得分:0)

根据https://drive.google.com/open?id=0B4DUWMYsjWtdVVRibDFZOVhac2s发布的代码,现在我很清楚你想要实现的目标。

您希望创建类(例如,服务)的层次结构,以定义每个级别的某些功能。例如:

  • RepoA定义了methodA方法。
  • RepoB延伸RepoA和 定义了methodB方法。
  • ServiceA使用RepoA类 揭露这种方法
  • ServiceB扩展ServiceA并公开其内容 方法和ServiceA方法
  • 等等......

调试你的应用程序,我发现Spring尝试创建一个新的AccountService bean而不是在调用此代码时使用现有的bean:

@Controller
@RequestMapping("/Account")
public class AccountController extends AbsBaseDataController<Account> {

    private AccountService service;

    @Autowired
    public AccountController(AccountService service) {
        super(service);
        this.service = service;
        System.out.println("AccountController-CONSTRUCTOR");
    }
}

这是因为您直接使用AccountService类,而不是界面。这是重要的,因为Spring会在您的类周围创建一个代理,以便能够在它们上使用AOP。因此,当涉及到自动装配它时,类不匹配(您认为类的实例被注入,但实际上是com.sun.proxy.Proxy)。

由于这些Java代理实现了您的类&#39;接口,您应该为AccountService创建一个界面(比如说IAccountService),然后在AccountService类&#39;中使用它来代替原始AccountController类。构造:

界面

public interface IAccountService extends BaseDataService<Account> {
}

控制器

@Controller
@RequestMapping("/Account")
public class AccountController extends AbsBaseDataController<Account> {

    private IAccountService service;

    @Autowired
    public AccountController(IAccountService service) {
        super(service);
        this.service = service;
        System.out.println("AccountController-CONSTRUCTOR");
    }
}

服务类

@Service
public class AccountService extends AbsBaseDataService<Account> implements IAccountService {
[...]
}