近日整合sping和hibernate框架時遇到了一系列的異常,本次主要說明一下spring框架可能出現的異常及解決方案。
我們借助sping強大的bean容器管理機制,通過BeanFactory輕松的實現javabean的生命周期管理,然而在配置管理的時候難免會遇到一些異常:
異常1:No qualifying bean of type […] found for dependency
例如將BeanB自動注入到BeanA
@Component
public class BeanA {@Autowired
private BeanB dependency;
…
}
如果此時BeanB沒有定義在sping的Cntextl里,那么在啟動時候就會拋出異常: the no such bean definition exception:
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type [org.baeldung.packageB.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)}
問題的原因很簡單 expected at least 1 bean which qualifies as autowire candidate for this dependency.至少需要要有一個定義的bean來依賴注入。當然還可能存在領一種原因就是,我們在使用注解,配置注解掃描的時候沒有設置對包掃描的路徑,那么除了這種情況之外就應該是沒有定義bean了。
異常2:No qualifying bean of type […] is defined
這個異常的意思就是沒有符合的類型Bean.原因是我們定義了兩個或者多個相同的bean而不是唯一的bean,例如有一個接口IBeanB,它的兩個實現類Bean1和Bean2
@Component
public class BeanB1 implements IBeanB {
//
}
@Component
public class BeanB2 implements IBeanB {
//
}
此時如果BeanA注入了接口IBeanB,Spring 就不知道使用哪個實現類來注入
@Component
public class BeanA {@Autowired
private IBeanB dependency;
…
}
此時,BeanFactory就會拋出異常NoSuchBeanDefinitionException
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException:
No qualifying bean of type [org.baeldung.packageB.IBeanB] is defined:
expected single matching bean but found 2: beanB1,beanB2
從異常 expected single matching bean but found 2”.可以看出未發現唯一的bean。
那么可以通過如下方法來解決
@Component
public class BeanA {@Autowired
@Qualifier(“beanB2”)
private IBeanB dependency;
…
}
sping 就會明確的知道是使用哪個Bean作為注入使用的對象。
異常3:No Bean Named […] is defined
當出現這個異常時,通過名字去Sping上下文查找bean,可能出現異常NoSuchBeanDefinitionException
@Component
public class BeanA implements InitializingBean {@Autowired
private ApplicationContext context;@Override
public void afterPropertiesSet() {
context.getBean(“someBeanName”);
}
}
這里在查找時,不存在名字為someBeanName的定義,導致異常
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException:
No bean named ‘someBeanName’ is defined
很清晰的指出,不存在此名字的bean定義。
異常4:Proxied Beans
當一個bean在spring上下文中使用JDK動態代理機制,那么代理類不會繼承目標對象,但它實現了相同的接口,因為這個原因,如果一個Bean注入了一個接口,那么不會出現問題,但是如果注入了是一個實現的類,Sping容器就會無法找到此時的bean,因為代理類沒有繼承目標類。一個bean被代理的原因很常見的一個場景就是使用spring的事務支持功能,可以使用注解@Transactional表示事務,也可以在配置文件里設置。
例如如果 ServiceA 注入 ServiceB, 並且同時兩個services 都配置了事務 ,通過類注入那么將會出現問題。
@Service
@Transactional
public class ServiceA implements IServiceA{@Autowired
private ServiceB serviceB;
…
}@Service
@Transactional
public class ServiceB implements IServiceB{
…
}
同樣是這兩個Services,如果使用接口注入將正常運行。
@Service
@Transactional
public class ServiceA implements IServiceA{@Autowired
private IServiceB serviceB;
…
}@Service
@Transactional
public class ServiceB implements IServiceB{
…
}
總結一下:
上面主要講述了幾種sping常見的NoSuchBeanDefinitionException類型異常,並且給出了相應的實踐代碼,在實踐過程中大家如果遇到問題可以隨時提問。