我试图在实现接口的应用程序上下文中加载类,遇到了两种情况
CriteriaQuerySampleDao dao= context.getBean(CriteriaQuerySampleDao.class);
当我的接口 GenericDao 确实声明了方法并且由我的类 CriteriaQuerySampleDao 实现时:
在这种情况下,按照下面的代码
CriteriaQuerySampleDao dao= context.getBean(CriteriaQuerySampleDao.class);
并抛出
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.journaldev.spring.config.CriteriaQuerySampleDao' available
但是当我通过使用类CriteriaQuerySampleDao的接口GenericDao的以下代码加载它时,它会成功地按以下代码加载
GenericDao dao= context.getBean(GenericDao.class);
有人可以解释为什么如果我的类只实现一种接口方法,为什么我不得不通过 GenericDao 接口加载 CriteriaQuerySampleDao 类。
我不确定细节,春天会习惯吗?
GenericDao界面
interface GenericDao<T>
{
Session getSession();
Class<T> getDefaultMappedObject();
}
CriteriaQuerySampleDao 实现GenericDao的类
@Transactional
@Repository
public class CriteriaQuerySampleDao implements GenericDao<MyDBTable>
{
protected final static Logger logger= LogManager.getLogger(CriteriaQuerySampleDao.class);
@Inject
SessionFactory sessionFactory;
@Override
public Session getSession()
{
Session session= null;
try
{
logger.debug(" ++++ getSession try ++++ ");
session= sessionFactory.getCurrentSession();
}catch(Exception ex)
{
logger.debug(" ++++ getSession catch ++++ ", ex);
session= sessionFactory.openSession();
}
return session;
}
@Override
public Class<MyDBTable> getDefaultMappedObject()
{ return MyDBTable.class; }
}
LocalHibernateConfig 类配置和具有主要方法的类:
@Configuration
@PropertySource(value= {"classpath:hibernate.properties"}, ignoreResourceNotFound= true)
@EnableTransactionManagement
@ComponentScan
@Component(value= "LocalHibernateConfig")
public class LocalHibernateConfig
{
public static void main(String[] args) throws Exception
{
AnnotationConfigApplicationContext context= new AnnotationConfigApplicationContext();
// context.getEnvironment().setActiveProfiles("local");
context.register(LocalHibernateConfig.class);
context.refresh();
LocalHibernateConfig lch= context.getBean(LocalHibernateConfig.class);
logger.debug(" ++++ Properties is null "+(lch.properties==null)+" properties: "+lch.getProperties());
CriteriaQuerySampleDao dao= context.getBean(CriteriaQuerySampleDao.class);
// GenericDao dao= context.getBean(GenericDao.class);
logger.debug(" ++++ dao: "+(dao==null));
}
}
答案 0 :(得分:0)
如果在构建时将代码覆盖工具(例如jacoco)连接到JVM,则会发生这种情况。它创建了一个Proxy类来处理覆盖范围,并且该Proxy类实现了您的接口,因此,虽然它是您接口的一个实例,但实际上并不是您Impl的一个实例。
答案 1 :(得分:0)
它与生成代理接口以启用事务支持的方式有关。您可以通过将SectionModel
的{{1}}属性设置为proxyTargetClass
来更改行为:
@EnableTransactionManagement
其背后的原因是true
是通过decorator pattern与动态生成的装饰器类一起实现的。
Spring可以通过两种方式创建动态装饰器:default java proxies或CGLib。只能为实现接口的类生成默认的Java代理。对于@EnableTransactionManagement(proxyTargetClass= true)
@ComponentScan
@Component(value= "LocalHibernateConfig")
public class LocalHibernateConfig {
}
,它实现了一个接口,因此Spring将诉诸于默认的Java代理。