Spring Boot: как получить доступ к репозиторию в java-классе @Autowired не работает
Пожалуйста, объясните свое решение с помощью образца кода, поскольку я новичок в Spring Boot.
Репозиторий
import java.util.List;
import org.springframework.data.repository.CrudRepository;
public interface StoreRepository extends CrudRepository<Store, Integer> {
List<Store> findAll();
}
Магазин сущностей
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class Store {
@Id
private Integer sid;
private String sname;
public Store() {
}
public Store(Integer sid, String sname) {
super();
this.sid = sid;
this.sname = sname;
}
///GETTER and Setters here...
}
** Сервис магазина **
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class StoreService {
@Autowired
private StoreRepository storeRepository;
public StoreService() {
}
public List<Stores> getAllStores(){
return (List<Stores>) storeRepository.findAll(); /* This works good. Through controller I can retrieve all data*/
}
}
Простой класс Java
@Component
public class StoreWorker {
@Autowired
private StoreRepository storeRepository;
public StoreWorker() {
System.out.println(storeRepository.findAll()); /* Error */
}
Ошибка :
Exception in thread "StoreWorker : restartedMain" java.lang.reflect.InvocationTargetException
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [io.store.workers.StoreWorker]: Constructor threw exception; nested exception is java.lang.NullPointerException
Caused by: java.lang.NullPointerException
Пожалуйста, объясните свое решение с помощью образца кода, поскольку я новичок в Spring Boot.
Вы должны использовать @Autowire на уровне конструктора, чтобы использовать переменную Autowire внутри конструктора.
@Component
public class StoreWorker {
@Autowired
public StoreWorker(StoreRepository storeRepository) {
System.out.println(storeRepository.findAll());
}
(или) Используйте PostConstruct
Автоэлектромонтаж происходит после постройки объекта. Поэтому они не будут установлены до тех пор, пока конструктор не завершит работу.
Если вам нужно запустить какой-то код инициализации, вы сможете вставить код в конструкторе в метод и аннотировать этот метод с помощью @PostConstruct.
Ребята, оставьте комментарий, а затем проголосуйте против ответа, чтобы, если в моем ответе есть какой-либо недостаток, я мог его исправить. Простое отрицательное голосование причиняет боль другим и перестает отвечать на другие вопросы в потоке стеков.
Аннотации @Repository не нужны при расширении интерфейса org.springframework.data.repository.Repository
@Matt Спасибо за ваш комментарий. Но упоминание репозитория не повредит классу, но это нормально. хотя я ответил на вопрос во второй части своего ответа. Вместо отрицательного голоса вы можете отредактировать ответ, верно? Это испортило мои выходные
И почему вы думаете, что я отклонил ваш ответ? Я просто комментировал
Отсутствие @Repository не является причиной того, что код не работает, как следует из вашего ответа. Вы должны поставить вторую часть первой, так как это основная причина. Не позволяйте этому испортить вам выходные;) По крайней мере, вы дали ответ, что всегда хорошо.
@ Мэтт Очень жаль. Я подумал, увидев ваше сообщение, что вы проголосовали против моего ответа, и я был очень зол.
Лучше использовать внедрение конструкции, как указано в других ответах, начиная с Spring 4.3, аннотация @Autowired больше не требуется! :-)
Вы должны изменить свой код следующим образом:
Если вы хотите использовать свой автоматически подключенный bean-компонент в конструкторе вашего класса, используйте внедрение конструктора. Это также наиболее рекомендуемый способ инъекции.
@Component
public class StoreWorker {
private final StoreRepository storeRepository;
public StoreWorker(StoreRepository storeRepository) {
this.storeRepository = storeRepository;
System.out.println(storeRepository.findAll());
}
}
Поэтому, когда создается экземпляр StoreWorker, внедряется автосоединенный компонент storeRepository. Поскольку это происходит, вы можете использовать bean-компонент storeRepository.
Вы не должны вкладывать в конструктор никакой логики. Методы конструктора предназначены только для инициализации вашего экземпляра.
Сделайте вызов storeRepository отдельным методом.
@Component
public class StoreWorker {
@Autowired
private StoreRepository storeRepository;
public void findAll() {
System.out.println(storeRepository.findAll());
}
}
Когда Spring вызывает ваш конструктор, контекст не полностью инициализирован, и, поскольку вы не используете внедрение конструктора, storeRepository еще не внедряется.
Внедрение конструктора - это рекомендуемый способ внедрения командой Spring. А начиная с Spring 4.3 вам даже не нужно добавлять аннотацию @Autowired к конструкторам.
@Component
public class StoreWorker {
private StoreRepository storeRepository;
//@Autowired not needed since v4.3
public StoreWorker(StoreRepository storeRepository) {
this.storeRepository = storeRepository;
}
...
}
Если вы хотите выполнить дальнейшую инициализацию вашего bean-компонента, полагаясь на другие внешние bean-компоненты, сделайте это отдельным методом, аннотированным @PostConstruct.
@Component
public class StoreWorker {
private StoreRepository storeRepository;
private List<Store> stores;
public StoreWorker(StoreRepository storeRepository) {
this.storeRepository = storeRepository;
}
@PostConstruct
public void initializeMyBean() {
stores = storeRepository.findAll();
}
}
Пробовал с аннотациями для репозитория, а также с компонентом, я все еще получаю System.out.println (storeRepository); = NULL