我有这个MovieService.java:
@Service
public class MovieService implements MovieInterface {
@Autowired
private MovieRepository movieRepository;
@Autowired
private UserRepository userRepository;
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
JwtUser user = (JwtUser)authentication.getPrincipal();
User current_user = userRepository.findOne(user.getId());
@Override
public Movie createMovie(Movie movie) {
current_user.addMovie(movie);
userRepository.save(current_user);
return movie;
}
}
这是我编译代码时遇到的错误:
org.springframework.beans.factory.UnsatisfiedDependencyException:创建名为'movieController'的bean时出错:通过字段'movieService'表示的不满意的依赖关系;嵌套异常是org.springframework.beans.factory.BeanCreationException:在文件[C:\ Users \ alucardu \ Documents \ projects \ movieseat \ backend \ target \ classes \ com \ movieseat \ services \]中定义名称为'movieService'的bean时出错MovieService.class]:bean的实例化失败;嵌套异常是org.springframework.beans.BeanInstantiationException:无法实例化[com.movieseat.services.MovieService]:构造函数抛出异常;嵌套异常是java.lang.NullPointerException
将authentication
,user
和current_user
属性移动到createMovie
方法时,此问题已得到解决。但是我想在多个方法中使用current_user
,所以我想将它添加为类成员。
我还实现了一个MovieInterface:
package com.movieseat.interfaces;
// Java imports
import java.util.List;
import com.movieseat.model.security.User;
// Project imports
import com.movieseat.models.Movie;
import com.movieseat.security.JwtUser;
import org.springframework.security.core.Authentication;
public interface MovieInterface {
List<Movie> getAllmovies();
Movie createMovie(Movie movie);
void deleteMovie(Integer id);
}
所以我想也许代码不能编译,因为在接口中没有定义属性authentication
,user
和current_user
。虽然我希望有类似的错误输出。当我将属性添加到界面时:
public interface MovieInterface {
Authentication authentication;
JwtUser user;
User current_user;
List<Movie> getAllmovies();
Movie createMovie(Movie movie);
void deleteMovie(Integer id);
}
我收到消息:
空白的最终字段验证可能尚未初始化
空白的最终字段用户可能尚未初始化
空白的最终字段current_user可能尚未初始化
此消息有意义,因为接口期望字段为final。而这些领域没有任何价值。所以我的问题是,我可以在界面中标记一个不是最终的字段吗?如果我必须初始化字段的值,我需要使用什么?
我知道你初始化一个字段String name = "name";
但这些属性是对象。
User current_user = {};
无法从Object []转换为User
答案 0 :(得分:3)
您的服务是一个bean,特别是它是一个单例。这意味着您的应用程序中只有一个此服务实例。
但它可能会被不同的用户调用。因此,您必须使用createMovie
方法获取当前用户(您已将其命名为当前用户!)。
当您尝试在PostConstruct方法中初始化这些字段时,您不会拥有SecurityContext并且您不会拥有主体。如果您在服务实例中保留有关当前用户的信息,那么无论他们来自何处,都将代表这一个用户进行所有呼叫。
所以最好的方法是创建一个方法:
private getUser() {
Authentication authentication =
SecurityContextHolder.getContext().getAuthentication();
JwtUser user = (JwtUser)authentication.getPrincipal();
User current_user = userRepository.findOne(user.getId());
return current_user;
}
并从您的不同方法中调用它。
答案 1 :(得分:1)
你的班级是一个豆子。这意味着,所有@Autowired字段都将从其他人(Spring或CDI)设置。问题是什么时候?您可能将bean A与自动连接的bean B作为属性,反之亦然。您需要等待,直到所有属性都已自动连线。您尝试在对象创建期间使用userRepository。那太早了。 Spring必须创建Java对象(没有办法解决这个问题),但之后会自动进行自动装配。但是通过依赖注入,如果使用@PostConstruct注释方法,则会在设置所有属性时告知您。
@PostConstruct
public void init(){
// it is safe now to use user repository, because it is not null anymore
}