Spring Boot UnsatisfiedDependencyException 创建名称为无法解析的循环引用的 bean 时出错

Posted

技术标签:

【中文标题】Spring Boot UnsatisfiedDependencyException 创建名称为无法解析的循环引用的 bean 时出错【英文标题】:Spring Boot UnsatisfiedDependencyException Error creating bean with name unresolvable circular reference 【发布时间】:2021-09-14 20:39:39 【问题描述】:

我正在使用 Spring Secuity 开发一个应用程序,其中有一些自定义过滤器,但我无法正确配置它们。考虑以下自定义过滤器:

LoginAuthenticationFilter:

package com.espiritware.opusclick.restfullbackend.security.filters;


public class LoginAuthenticationFilter extends OncePerRequestFilter
    
    private static final String TOKEN_PREFIX = "Bearer ";
    private static final String HEADER_STRING = "Authorization";
    private String credentialsCharset = "UTF-8";

    @Autowired
    private AuthenticationManager authenticationManager;
    
    @Autowired
    private TokenService tokenService;
    
    
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException 
        
        String header = request.getHeader("Authorization");
        
        if (header == null || !header.startsWith("Basic ")) 
            filterChain.doFilter(request, response);
            return;
        
        
        String[] tokens = extractAndDecodeHeader(header, request);
        String email = tokens[0];
        String password = tokens[1];
        
        
        if(request.getServletPath().equals("/login/user")) 
            LoginAuthenticationFilter opusClickAuth= new OpusClickLoginAuthentication(email,password,true);
            try 
                Authentication result=authenticationManager.authenticate(opusClickAuth);
                if(result.isAuthenticated()) 
                    //SecurityContextHolder.getContext().setAuthentication(result);
                    String jwtToken=tokenService.createAuthenticationToken(result,true);
                    response.addHeader("Access-Control-Expose-Headers", "Authorization");
                    response.addHeader(HEADER_STRING, TOKEN_PREFIX + jwtToken);
                    response.setHeader("Content-Type", "application/json");
                
            catch(AuthenticationException failed) 
                //SecurityContextHolder.clearContext();
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            
        
        else 
            LoginAuthenticationFilter opusClickAuth= new OpusClickLoginAuthentication(email,password,false);
            try 
                Authentication result=authenticationManager.authenticate(opusClickAuth);
                if(result.isAuthenticated()) 
                    //SecurityContextHolder.getContext().setAuthentication(result);
                    String jwtToken=tokenService.createAuthenticationToken(result,false);
                    response.addHeader("Access-Control-Expose-Headers", "Authorization");
                    response.addHeader(HEADER_STRING, TOKEN_PREFIX + jwtToken);
                    response.setHeader("Content-Type", "application/json");
                
            catch(AuthenticationException failed) 
                //SecurityContextHolder.clearContext();
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            
        
    
    
    protected String[] extractAndDecodeHeader(String header, HttpServletRequest request)
            throws IOException 

        byte[] base64Token = header.substring(6).getBytes("UTF-8");
        byte[] decoded;
        try 
            decoded = Base64.getDecoder().decode(base64Token);
        
        catch (IllegalArgumentException e) 
            throw new BadCredentialsException(
                    "Failed to decode basic authentication token");
        

        String token = new String(decoded, getCredentialsCharset(request));

        int delim = token.indexOf(":");

        if (delim == -1) 
            throw new BadCredentialsException("Invalid basic authentication token");
        
        return new String[]  token.substring(0, delim), token.substring(delim + 1) ;
    
    
    protected String getCredentialsCharset(HttpServletRequest httpRequest) 
        return this.credentialsCharset;
    
    
    
    //No debe filtrar
    //false -> se activa
    //true -> no se activa
    @Override
    protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException 
        if(request.getServletPath().equals("/login/user")|| request.getServletPath().equals("/login/expert"))
            return false;
        
        else 
            return true;
        
    


JwtAuthenticationFilter:

package com.espiritware.opusclick.restfullbackend.security.filters;

public class JwtAuthenticationFilter extends OncePerRequestFilter
    
    @Autowired
    private AuthenticationManager authenticationManager;
    
    @Autowired
    private TokenService tokenService;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException 
        
        String header = request.getHeader("Authorization");
        
        if (header == null || !header.startsWith("Bearer ")) 
            filterChain.doFilter(request, response);
            return;
        
        
        String jwtToken=extractToken(header);
        JwtAuthentication jwtAuthentication = new JwtAuthentication(jwtToken);
        
        try 
            Authentication result=authenticationManager.authenticate(jwtAuthentication);
            SecurityContextHolder.getContext().setAuthentication(result);
            filterChain.doFilter(request, response);
        catch(AuthenticationException failed) 
            SecurityContextHolder.clearContext();
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        
        authenticationManager.authenticate(jwtAuthentication);
    
    
    protected String extractToken(String header)

        int delim = header.indexOf(" ");

        if (delim == -1) 
            throw new BadCredentialsException("Invalid authentication token");
        
        return header.substring(delim + 1);
    
    
    
    @Override
    protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException 
        if(request.getServletPath().equals("/login/user")|| request.getServletPath().equals("/login/expert"))
            return true;
        
        else 
            return false;
        
    


过滤器配置:

package com.espiritware.opusclick.restfullbackend.security.filters.configurations;
@Configuration
public class FilterConfigurations 
    
    @Bean
    public LoginAuthenticationFilter opusClickLoginAuthenticationFilter() 
        return new OpusClickLoginAuthenticationFilter();
    
    
    @Bean
    public JwtAuthenticationFilter jwtAuthenticationFilter() 
        return new JwtAuthenticationFilter();
    
    

WebAppSecurityConfiguration:(失败)

package com.espiritware.opusclick.restfullbackend.security;

@Configuration
public class WebAppSecurityConfiguration extends WebSecurityConfigurerAdapter 
        
    @Autowired
    private LoginAuthenticationFilter opusClickLoginAuthenticationFilter;
    
    @Autowired
    private JwtAuthenticationFilter jwtAuthenticationFilter;
    
     @Override
     protected void configure(HttpSecurity http) throws Exception 
         //http.oauth2Client();
         http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
         
         http.addFilterAt(LoginAuthenticationFilter,
                    BasicAuthenticationFilter.class)
              .addFilterAt(jwtAuthenticationFilter, 
                    BasicAuthenticationFilter.class);
         
         http.authorizeRequests()
                .anyRequest()
                .authenticated()
            .and()  
                .httpBasic();
         
         
     
     
     
    @Bean
    public PasswordEncoder passwordEncoder() 
        return new BCryptPasswordEncoder();
    
    
//  @Bean
//  public LoginAuthenticationFilter LoginAuthenticationFilter() 
//      return new LoginAuthenticationFilter();
//  
    
//  @Bean
//  public JwtAuthenticationFilter jwtAuthenticationFilter() 
//      return new JwtAuthenticationFilter();
//  
    
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception 
        return super.authenticationManagerBean();
    


当我运行应用程序时,它会抛出以下异常:

org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:163) ~[spring-boot-2.5.1.jar:2.5.1]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:577) ~[spring-context-5.3.8.jar:5.3.8]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145) ~[spring-boot-2.5.1.jar:2.5.1]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-2.5.1.jar:2.5.1]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:434) ~[spring-boot-2.5.1.jar:2.5.1]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:338) ~[spring-boot-2.5.1.jar:2.5.1]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343) ~[spring-boot-2.5.1.jar:2.5.1]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1332) ~[spring-boot-2.5.1.jar:2.5.1]
    at com.espiritware.opusclick.restfullbackend.OpusClickRestfullBackendApplication.main(OpusClickRestfullBackendApplication.java:10) ~[classes/:na]
Caused by: org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat
    at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize(TomcatWebServer.java:142) ~[spring-boot-2.5.1.jar:2.5.1]
    at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.<init>(TomcatWebServer.java:104) ~[spring-boot-2.5.1.jar:2.5.1]
    at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getTomcatWebServer(TomcatServletWebServerFactory.java:450) ~[spring-boot-2.5.1.jar:2.5.1]
    at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getWebServer(TomcatServletWebServerFactory.java:199) ~[spring-boot-2.5.1.jar:2.5.1]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:182) ~[spring-boot-2.5.1.jar:2.5.1]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:160) ~[spring-boot-2.5.1.jar:2.5.1]
    ... 8 common frames omitted
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'LoginAuthenticationFilter': Unsatisfied dependency expressed through field 'authenticationManager'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'webAppSecurityConfiguration': Unsatisfied dependency expressed through field 'jwtAuthenticationFilter'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'jwtAuthenticationFilter': Unsatisfied dependency expressed through field 'authenticationManager'; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'authenticationManagerBean': Requested bean is currently in creation: Is there an unresolvable circular reference?
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:660) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:640) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1413) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:601) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:213) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.boot.web.servlet.ServletContextInitializerBeans.getOrderedBeansOfType(ServletContextInitializerBeans.java:212) ~[spring-boot-2.5.1.jar:2.5.1]
    at org.springframework.boot.web.servlet.ServletContextInitializerBeans.addAsRegistrationBean(ServletContextInitializerBeans.java:175) ~[spring-boot-2.5.1.jar:2.5.1]
    at org.springframework.boot.web.servlet.ServletContextInitializerBeans.addAsRegistrationBean(ServletContextInitializerBeans.java:170) ~[spring-boot-2.5.1.jar:2.5.1]
    at org.springframework.boot.web.servlet.ServletContextInitializerBeans.addAdaptableBeans(ServletContextInitializerBeans.java:155) ~[spring-boot-2.5.1.jar:2.5.1]
    at org.springframework.boot.web.servlet.ServletContextInitializerBeans.<init>(ServletContextInitializerBeans.java:87) ~[spring-boot-2.5.1.jar:2.5.1]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.getServletContextInitializerBeans(ServletWebServerApplicationContext.java:260) ~[spring-boot-2.5.1.jar:2.5.1]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.selfInitialize(ServletWebServerApplicationContext.java:234) ~[spring-boot-2.5.1.jar:2.5.1]
    at org.springframework.boot.web.embedded.tomcat.TomcatStarter.onStartup(TomcatStarter.java:53) ~[spring-boot-2.5.1.jar:2.5.1]
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5161) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1384) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1374) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[na:na]
    at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:140) ~[na:na]
    at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:909) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:829) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1384) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1374) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[na:na]
    at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:140) ~[na:na]
    at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:909) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:262) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    at org.apache.catalina.core.StandardService.startInternal(StandardService.java:433) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:930) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    at org.apache.catalina.startup.Tomcat.start(Tomcat.java:486) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize(TomcatWebServer.java:123) ~[spring-boot-2.5.1.jar:2.5.1]
    ... 13 common frames omitted
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'webAppSecurityConfiguration': Unsatisfied dependency expressed through field 'jwtAuthenticationFilter'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'jwtAuthenticationFilter': Unsatisfied dependency expressed through field 'authenticationManager'; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'authenticationManagerBean': Requested bean is currently in creation: Is there an unresolvable circular reference?
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:660) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:640) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1413) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:601) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:410) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1334) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1177) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:564) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1380) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1300) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:657) ~[spring-beans-5.3.8.jar:5.3.8]
    ... 55 common frames omitted
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'jwtAuthenticationFilter': Unsatisfied dependency expressed through field 'authenticationManager'; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'authenticationManagerBean': Requested bean is currently in creation: Is there an unresolvable circular reference?
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:660) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:640) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1413) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:601) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1380) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1300) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:657) ~[spring-beans-5.3.8.jar:5.3.8]
    ... 78 common frames omitted
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'authenticationManagerBean': Requested bean is currently in creation: Is there an unresolvable circular reference?
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.beforeSingletonCreation(DefaultSingletonBeanRegistry.java:355) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:227) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1380) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1300) ~[spring-beans-5.3.8.jar:5.3.8]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:657) ~[spring-beans-5.3.8.jar:5.3.8]
    ... 92 common frames omitted

但是,当我评论整个 FilterConfigurations 类并直接在 WebAppSecurityConfiguration 中配置过滤器 bean 时,它可以正常工作:

WebAppSecurityConfiguration:(正常工作)

package com.espiritware.opusclick.restfullbackend.security;

@Configuration
public class WebAppSecurityConfiguration extends WebSecurityConfigurerAdapter 
        
    //@Autowired
    //private LoginAuthenticationFilter opusClickLoginAuthenticationFilter;
    
    //@Autowired
    //private JwtAuthenticationFilter jwtAuthenticationFilter;
    
     @Override
     protected void configure(HttpSecurity http) throws Exception 
         //http.oauth2Client();
         http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
         
         http.addFilterAt(LoginAuthenticationFilter(),
                    BasicAuthenticationFilter.class)
              .addFilterAt(jwtAuthenticationFilter(), 
                    BasicAuthenticationFilter.class);
         
         http.authorizeRequests()
                .anyRequest()
                .authenticated()
            .and()  
                .httpBasic();
         
         
     
     
     
    @Bean
    public PasswordEncoder passwordEncoder() 
        return new BCryptPasswordEncoder();
    
    
    @Bean
    public LoginAuthenticationFilter LoginAuthenticationFilter() 
        return new LoginAuthenticationFilter();
    
    
    @Bean
    public JwtAuthenticationFilter jwtAuthenticationFilter() 
        return new JwtAuthenticationFilter();
    
    
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception 
        return super.authenticationManagerBean();
    


我的问题是,当我在 FilterConfigurations 中执行 相同的配置 时,为什么会停止工作。我不知道是不是因为这个类在另一个包中找到。谁能解释这种奇怪行为的原因?

非常感谢!

【问题讨论】:

我认为LoginAuthenticationFilterJwtAuthenticationFilter类也需要用@Configuration注解。请检查这是否有效。 这两个过滤器都是不必要的,因为 spring security 已经支持基本登录(base64 enc 标头)并且已经在 spring security 5 @987654321 中实现了一个 JWTFilter @我不明白使用框架的意义如果你打算构建已经在框架中的东西? 【参考方案1】:

要消除此问题,您必须在 WebSecurity 类之外创建一个 bean,因为我注意到 @autowired 和 @bean 有时会被容器搞砸,原因是他无法在运行时识别对象。

    @Component
public class PasswordEncoderConfiguration 

    @Bean
    BCryptPasswordEncoder passwordEncoder()
        return new BCryptPasswordEncoder();
    

您必须使用下面的方法将其自动连接到 Websecurityconfig 类,

@Autowired
private BCryptPasswordEncoder passwordEncoder;

    @Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception 
    // configure AuthenticationManager so that it knows from where to load
    // user for matching credentials
    // Use BCryptPasswordEncoder
    auth.userDetailsService(jwtUserDetailsService).passwordEncoder(passwordEncoder);

【讨论】:

【参考方案2】:

问题肯定与两个注释有关:@Autowired 用于过滤器,@Bean 注释用于authenticationManagerBean 方法。首先需要了解WebAppSecurityConfiguration 类将在两个过滤器都被自动装配时准备好使用,但是为了成功自动装配两个过滤器与AuthenticationManager 有关系,并且对于那个目标,我们通过@Bean 注释标记了方法authenticationManagerBean ,并且 Spring 尝试通过以下方式创建 AuthenticationManager

public AuthenticationManager authenticationManagerBean() throws Exception 
    return new AuthenticationManagerDelegator(this.authenticationBuilder, this.context);

正如您在创建AuthenticationManagerDelegator 时看到的那样,我们应该已经初始化了两个字段authenticationBuildercontext,但是我们刚刚开始创建我们的WebAppSecurityConfiguration 配置bean,它将被标记为创建时,直到所有字段都被初始化,它是专门为避免使用未初始化的字段和获得NullPointerException 异常而设计的。 但是如果查看 bean 定义的第二个选项,bean 创建的工作流程发生了如下变化:

    WebAppSecurityConfiguration 没有用于自动装配的字段,我们可以轻松地首先创建配置 bean 并取消标记,如 in creation 在创建配置bean之后,所有@Bean注解都将被处理并且在创建authenticationManagerBean时我们不会得到异常,因为在我们创建WebAppSecurityConfiguration配置时所有的字段都被初始化了,现在我们可以使用所有的父安全的方法。

附:从我的角度来看,通过以下方式定义 bean:

@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception 
    return super.authenticationManagerBean();

这不是一个好主意,因为WebSecurityConfigurerAdapter 类将按正确的顺序创建所有必需的组件(bean),并且父类中的这些方法已打开以通过以下方式自定义实现 bean:

@Override
public AuthenticationManager authenticationManagerBean() throws Exception 
    return new CustomAuthenticationManager(...);

【讨论】:

这是完美的解释。理想情况下,我们不应该在 Configuration 类中使用 Autowired,因为 Configuration 类用于 bean 定义和布线,所以很明显,当 spring 执行 bean 布线时,它不能注入 Autowired 对象,这些对象可能具有尚未初始化的依赖对象,并且它给出了 InCreationException。 【参考方案3】:

@Configuration 是给 Bean 配置的,不能用 @Autowired 自动注入普通的 bean,好像只支持这两种注入 1)@Value("$bean.name") String beanName; 2)@Inject 环境环境;环境是春天的特殊豆

WebAppSecurityConfiguration 更像是一个@Component Bean,而不是@Configuration Bean,你可以将@Component 和@Autowired 一起使用来注入过滤器Bean。

@Configuration 仅用于 Bean 配置,如果 DemoService 有 @Service 注解,则可以在 @Configuration 类中以这种方式注入它

@Bean
public JwtAuthenticationFilter jwtAuthenticationFilter(DemoService demoService) 
    return new JwtAuthenticationFilter(demoService);
 

【讨论】:

是的。我可以使用“@Autowired”在我的带注释的“@configuration”类中自动注入公共bean,这个工作正常。例如,如果我想在同一个类中使用“@Autowired”配置身份验证提供程序。例如,这对我有用:@Configuration public class WebAppSecurityConfiguration extends WebSecurityConfigurerAdapter @Autowired private JwtAuthenticationProvider jwtAuthenticationProvider; @Override protected void configure(AuthenticationManagerBuilder auth) auth.authenticationProvider(jwtAuthenticationProvider);

以上是关于Spring Boot UnsatisfiedDependencyException 创建名称为无法解析的循环引用的 bean 时出错的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Spring Boot 应用程序 pom 同时需要 spring-boot-starter-parent 和 spring-boot-starter-web?

《02.Spring Boot连载:Spring Boot实战.Spring Boot核心原理剖析》

spring-boot-quartz, 依赖spring-boot-parent

spring-boot系列:初试spring-boot

Spring Boot:Spring Boot启动原理分析

Spring Boot:Spring Boot启动原理分析