简体   繁体   English

注入的Bean在抽象类中为null

[英]Injected Beans are null in abstract class

I have abstract user service where I autowired two beans: Repository and AbstractMapper, but when I run test for that class, all faild with NullPointerException. 我有抽象的用户服务,在其中我自动连接了两个bean:Repository和AbstractMapper,但是当我对该类运行测试时,由于NullPointerException而全部失败。 When I run, for example, save test for that service in dubug, it show me that both beans are null. 例如,当我运行时,将服务的测试保存在dubug中,这表明两个bean均为空。 Anybody had this problem? 有人遇到这个问题吗? This is my code: 这是我的代码:

AbstractService AbstractService

package com.example.shop.service;

import com.example.shop.dto.AbstractMapper;
import com.example.shop.entity.Identifable;
import com.example.shop.repository.IRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

@Service`enter code here`
public abstract class AbstractService<E extends Identifable, D> implements IService<E, D> {

private IRepository<E> repository;
private AbstractMapper<E, D> abstractMapper;

@Autowired
public AbstractService(IRepository<E> repository, AbstractMapper<E, D> abstractMapper) {
    this.repository = repository;
    this.abstractMapper = abstractMapper;
}

@Override
public D get(Long id) {
    E e = repository.get(id);
    return abstractMapper.entityToDto(e);
}

@Override
public List<D> getAll() {
    List<E> all = repository.getAll();
    List<D> allDtos = all.stream()
            .map(e -> abstractMapper.entityToDto(e))
            .collect(Collectors.toList());
    return allDtos;
}

@Override
public E save(D d) {
    E e = abstractMapper.dtoToEntity(d);
    return repository.save(e);
}

@Override
public E update(D d) {
    E e = abstractMapper.dtoToEntity(d);
    return repository.update(e);
}

@Override
public E delete(D d) {
    E e = abstractMapper.dtoToEntity(d);
    return repository.delete(e);
}

@Override
public void deleteAll() {
    repository.deleteAll();
}
}

UserServiceImpl UserServiceImpl

package com.example.shop.service;

import com.example.shop.dto.UserDto;
import com.example.shop.dto.UserMapper;
import com.example.shop.entity.User;
import com.example.shop.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
 public class UserServiceImpl extends AbstractService<User, UserDto> implements UserService {

private UserRepository repository;
private UserMapper userMapper;

@Autowired
public UserServiceImpl(UserRepository repository, UserMapper userMapper) {
    super(repository, userMapper);
}
}

Abstract Mapper 抽象映射器

package com.example.shop.dto;

import org.springframework.stereotype.Component;

@Component
public interface AbstractMapper<E, D> {

 E dtoToEntity(D d);
 D entityToDto(E e);
 }

User Mapper: 用户映射器:

package com.example.shop.dto;

import com.example.shop.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class UserMapper implements AbstractMapper<User, UserDto> {

private AccountMapper accountMapper;

@Autowired
public UserMapper(AccountMapper accountMapper) {
    this.accountMapper = accountMapper;
}

@Override
public User dtoToEntity(UserDto dto) {
    if (dto == null) {
        return null;
    }
    User user = new User();
    user.setId(dto.getId());
    user.setEmail(dto.getEmail());
    user.setPassword(dto.getPassword());
    user.setLogin(dto.getLogin());
    user.setAccount(accountMapper.dtoToEntity(dto.getAccountDto()));
    return user;
}

@Override
public UserDto entityToDto(User user) {
    if (user == null) {
        return null;
    }
    UserDto dto = new UserDto();
    dto.setEmail(user.getEmail());
    dto.setLogin(user.getLogin());
    dto.setPassword(user.getPassword());
    dto.setId(user.getId());
    dto.setAccountDto(accountMapper.entityToDto(user.getAccount()));
    return dto;
}
}

Class with @SpringBootApplication @SpringBootApplication类

package com.example.shop;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ShopApplication implements CommandLineRunner {

public static void main(String[] args) {
    SpringApplication.run(ShopApplication.class, args);
}

@Override
public void run(String... args) throws Exception {
    System.out.println("Test");
}
}

And my tests for Service: 我对服务的测试:

package com.example.shop.service;

import com.example.shop.dto.UserDto;
import com.example.shop.entity.User;
import com.example.shop.repository.IRepository;
import org.junit.After; 
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import static org.mockito.Mockito.*;

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserServiceImplTest {

private static final Long VALID_ID = 1L;

@Mock
private IRepository<User> repository;

@InjectMocks
private UserServiceImpl service;

@After
public void tearDown() {
    repository.deleteAll();
}

@Test
public void get() {
    service.get(VALID_ID);

    verify(repository, times(1)).get(anyLong());
}

@Test
public void save() {
    UserDto dto = createUser();
    service.save(dto);

    verify(repository, times(1)).save(any());
}

@Test
public void getAll() {
    service.getAll();
    verify(repository, times(1)).getAll();
}

@Test
public void update() {
    UserDto dto = createUser();
    service.update(dto);
    verify(repository, times(1)).update(any());
}

@Test
public void delete() {
    UserDto dto = createUser();
    service.delete(dto);

    verify(repository, times(1)).delete(any());
}

@Test
public void deleteAll() {
    service.deleteAll();

    verify(repository, times(1)).deleteAll();
}

private UserDto createUser() {
    return new UserDto();
}


}

There are several problems with this code. 此代码存在几个问题。 First of all you do not need to annotate the abstract classes with service or component. 首先,您不需要使用服务或组件对抽象类进行注释。 Abstract classes cannot be instantiated, therefore there is no bean. 抽象类无法实例化,因此没有bean。 Second: autowire of classes having generics wont work. 第二:具有泛型的类的自动装配不起作用。 As soon as you have several bean, it wont be unique anymore. 一旦有了几个bean,它就不再是唯一的了。 Checkout if your classes get instantiated. 检出您的类是否被实例化。 Maybe you need to add @componentscan. 也许您需要添加@componentscan。

Your test is located under: com.example.shop.service and therefore it only scans the beans under this package. 您的测试位于com.example.shop.service下,因此它仅扫描此程序包下的bean。 You should either move your test or add the beans by using the componentscan annotation 您应该移动测试或通过使用componentscan批注添加bean

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM