Spring BeanCreationException
1. Visão geral
Neste artigo, estamos discutindo oSpring org.springframework.beans.factory.BeanCreationException - esta é uma exceção muito comum lançada quando oBeanFactory cria beans das definições de bean e encontra um problema. O artigo discutirá as causas mais comuns dessa exceção, juntamente com a solução.
Leitura adicional:
Introdução à Inversão do Controle e Injeção de Dependência com Mola
Uma rápida introdução aos conceitos de Inversão de Controle e Injeção de Dependência, seguida de uma demonstração simples usando o Spring Framework
Interfaces BeanNameAware e BeanFactoryAware na primavera
Dê uma olhada no trabalho com as interfaces BeanNameAware e BeanFactoryAware no Spring.
Registro do Bean Funcional da Primavera 5
Veja como registrar beans usando a abordagem funcional no Spring 5.
2. Causa:org.springframework.beans.factory.NoSuchBeanDefinitionException
De longe, a causa mais comum deBeanCreationException é o Spring tentandoinject a bean that doesn’t exist no contexto.
Por exemplo,BeanA está tentando injetarBeanB:
@Component
public class BeanA {
@Autowired
private BeanB dependency;
...
}
Se aBeanB não for encontrado no contexto, a seguinte exceção será lançada (Erro ao criar o bean):
Error creating bean with name 'beanA': Injection of autowired dependencies failed;
nested exception is org.springframework.beans.factory.BeanCreationException:
Could not autowire field: private org.example.web.BeanB org.example.web.BeanA.dependency;
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type [org.example.web.BeanB] found for dependency:
expected at least 1 bean which qualifies as autowire candidate for this dependency.
Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
Para diagnosticar esse tipo de problema - primeiro, verifique se o bean está declarado:
-
em um arquivo de configuração XML usando o elemento<bean />
-
ou em uma classe Java@Configuration por meio da anotação@Bean
-
ou é anotado com:@Component,@Repository,@Service,@Controllere a varredura de caminho de classe está ativa para esse pacote
Verifique também se os arquivos ou classes de configuração são realmente selecionados pelo Spring e carregados no contexto principal.
Leitura adicional:
Introdução à Inversão do Controle e Injeção de Dependência com Mola
Uma rápida introdução aos conceitos de Inversão de Controle e Injeção de Dependência, seguida de uma demonstração simples usando o Spring Framework
Interfaces BeanNameAware e BeanFactoryAware na primavera
Dê uma olhada no trabalho com as interfaces BeanNameAware e BeanFactoryAware no Spring.
Registro do Bean Funcional da Primavera 5
Veja como registrar beans usando a abordagem funcional no Spring 5.
3. Causa:org.springframework.beans.factory.NoUniqueBeanDefinitionException
Outra causa semelhante para a exceção de criação de bean é o Spring tentando injetar um bean por tipo - ou seja, por sua interface - e encontrandotwo or more bean implementing that interface no contexto.
Por exemplo,BeanB1 eBeanB2 implementam a mesma interface:
@Component
public class BeanB1 implements IBeanB { ... }
@Component
public class BeanB2 implements IBeanB { ... }
@Component
public class BeanA {
@Autowired
private IBeanB dependency;
...
}
Isso fará com que a seguinte exceção seja lançada pela fábrica de feijão Spring:
Error creating bean with name 'beanA': Injection of autowired dependencies failed;
nested exception is org.springframework.beans.factory.BeanCreationException:
Could not autowire field: private org.example.web.IBeanB org.example.web.BeanA.b;
nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException:
No qualifying bean of type [org.example.web.IBeanB] is defined:
expected single matching bean but found 2: beanB1,beanB2
4. Causa:org.springframework.beans.BeanInstantiationException
4.1. Exceção personalizada
O próximo na linha é umbean that throws an exception during its creation process; uma amostra simplificada para exemplificar e compreender facilmente o problema está lançando uma exceção no construtor do bean:
@Component
public class BeanA {
public BeanA() {
super();
throw new NullPointerException();
}
...
}
Como esperado, isso fará com que o Spring falhe rapidamente, com a seguinte exceção:
Error creating bean with name 'beanA' defined in file [...BeanA.class]:
Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException:
Could not instantiate bean class [org.example.web.BeanA]:
Constructor threw exception;
nested exception is java.lang.NullPointerException
4.2. java.lang.InstantiationException
Outra possível ocorrência deBeanInstantiationException é definir uma classe abstrata como um bean em XML; isso tem que ser em XML, porque não há como fazer isso em um arquivo Java @Configuration e a varredura do classpath irá ignorar a classe abstrata:
@Component
public abstract class BeanA implements IBeanA { ... }
E a definição XML do bean:
Essa configuração resultará em uma exceção semelhante:
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'beanA' defined in class path resource [beansInXml.xml]:
Instantiation of bean failed;
nested exception is org.springframework.beans.BeanInstantiationException:
Could not instantiate bean class [org.example.web.BeanA]:
Is it an abstract class?;
nested exception is java.lang.InstantiationException
4.3. java.lang.NoSuchMethodException
Se um bean não tiver construtor padrão e o Spring tentar instancia-lo procurando por esse construtor, isso resultará em uma exceção de tempo de execução; por exemplo:
@Component
public class BeanA implements IBeanA {
public BeanA(final String name) {
super();
System.out.println(name);
}
}
Quando esse bean é capturado pelo mecanismo de verificação do caminho de classe, a falha será:
Error creating bean with name 'beanA' defined in file [...BeanA.class]: Instantiation of bean failed;
nested exception is org.springframework.beans.BeanInstantiationException:
Could not instantiate bean class [org.example.web.BeanA]:
No default constructor found;
nested exception is java.lang.NoSuchMethodException: org.example.web.BeanA.()
Uma exceção semelhante, mas mais difícil de diagnosticar, pode ocorrer quando as dependências do Spring no classpath não têmsame version; este tipo de incompatibilidade de versão pode resultar emNoSuchMethodException devido a alterações de API. A solução para esse problema é garantir que todas as bibliotecas Spring tenham exatamente a mesma versão no projeto.
5. Causa:org.springframework.beans.NotWritablePropertyException
Outra possibilidade é definir um bean -BeanA - com uma referência a outro bean -BeanB - sem ter o método setter correspondente emBeanA:
@Component
public class BeanA {
private IBeanB dependency;
...
}
@Component
public class BeanB implements IBeanB { ... }
E a configuração XML da primavera:
Novamente, estecan only occur in XML Configuration, porque ao usar Java@Configuration, o compilador tornará este problema impossível de reproduzir.
Claro, para resolver esse problema, o setter precisa ser adicionado paraIBeanB:
@Component
public class BeanA {
private IBeanB dependency;
public void setDependency(final IBeanB dependency) {
this.dependency = dependency;
}
}
6. Causa:org.springframework.beans.factory.CannotLoadBeanClassException
Essa exceção é lançada quandoSpring cannot load the class of the defined bean - isso pode ocorrer se a configuração Spring XML contiver um bean que simplesmente não possui uma classe correspondente. Por exemplo, se a classeBeanZ não existir, a seguinte definição resultará em uma exceção:
A causa raiz seClassNotFoundExceptione a exceção completa neste caso for:
nested exception is org.springframework.beans.factory.BeanCreationException:
...
nested exception is org.springframework.beans.factory.CannotLoadBeanClassException:
Cannot find class [org.example.web.BeanZ] for bean with name 'beanZ'
defined in class path resource [beansInXml.xml];
nested exception is java.lang.ClassNotFoundException: org.example.web.BeanZ
7. Filhos deBeanCreationException
7.1. Oorg.springframework.beans.factory.BeanCurrentlyInCreationException
Uma das subclasses deBeanCreationException éBeanCurrentlyInCreationException; isso geralmente ocorre ao usar injeção de construtor - por exemplo, em um caso de dependências circulares:
@Component
public class BeanA implements IBeanA {
private IBeanB beanB;
@Autowired
public BeanA(final IBeanB beanB) {
super();
this.beanB = beanB;
}
}
@Component
public class BeanB implements IBeanB {
final IBeanA beanA;
@Autowired
public BeanB(final IBeanA beanA) {
super();
this.beanA = beanA;
}
}
O Spring não poderá resolver esse tipo de cenário de fiação e o resultado final será:
org.springframework.beans.factory.BeanCurrentlyInCreationException:
Error creating bean with name 'beanA':
Requested bean is currently in creation: Is there an unresolvable circular reference?
A exceção completa é muito detalhada:
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'beanA' defined in file [...BeanA.class]:
Unsatisfied dependency expressed through constructor argument with index 0
of type [org.example.web.IBeanB]: :
Error creating bean with name 'beanB' defined in file [...BeanB.class]:
Unsatisfied dependency expressed through constructor argument with index 0
of type [org.example.web.IBeanA]: :
Error creating bean with name 'beanA': Requested bean is currently in creation:
Is there an unresolvable circular reference?;
nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException:
Error creating bean with name 'beanA':
Requested bean is currently in creation:
Is there an unresolvable circular reference?;
nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'beanB' defined in file [...BeanB.class]:
Unsatisfied dependency expressed through constructor argument with index 0
of type [org.example.web.IBeanA]: :
Error creating bean with name 'beanA':
Requested bean is currently in creation:
Is there an unresolvable circular reference?;
nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException:
Error creating bean with name 'beanA':
Requested bean is currently in creation: Is there an unresolvable circular reference?
7.2. Oorg.springframework.beans.factory.BeanIsAbstractException
Essa exceção de instanciação pode ocorrer quando o Bean Factory tenta recuperar e instanciar um bean que foi declarado como abstrato; por exemplo:
public abstract class BeanA implements IBeanA {
...
}
Declarado na configuração XML como:
Agora, se tentarmosretrieve BeanA from the Spring Context by name - por exemplo, ao instanciar outro bean:
@Configuration
public class Config {
@Autowired
BeanFactory beanFactory;
@Bean
public BeanB beanB() {
beanFactory.getBean("beanA");
return new BeanB();
}
}
Isso resultará na seguinte exceção:
org.springframework.beans.factory.BeanIsAbstractException:
Error creating bean with name 'beanA': Bean definition is abstract
E o stacktrace de exceção completo:
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'beanB' defined in class path resource
[org/example/spring/config/WebConfig.class]: Instantiation of bean failed;
nested exception is org.springframework.beans.factory.BeanDefinitionStoreException:
Factory method
[public org.example.web.BeanB org.example.spring.config.WebConfig.beanB()] threw exception;
nested exception is org.springframework.beans.factory.BeanIsAbstractException:
Error creating bean with name 'beanA': Bean definition is abstract
8. Conclusão
No final deste artigo, devemos ter um mapa claro para navegar pela variedade de causas e problemas que podem levar aBeanCreationException no Spring, bem como uma boa compreensão de como consertar todos esses problemas.
A implementação de todos os exemplos de exceções pode ser encontrada emthe github project - este é um projeto baseado em Eclipse, portanto, deve ser fácil de importar e executar como está.