为什么只在Spring Application Context中

时间:2019-03-27 13:37:02

标签: java spring spring-mvc

我试图在实现接口的应用程序上下文中加载类,遇到了两种情况

  1. 当接口 GenericDao 没有任何声明的方法时: 在这种情况下,我的类CriteriaQuerySampleDao根据应用程序上下文中的以下代码加载,没有问题
CriteriaQuerySampleDao dao= context.getBean(CriteriaQuerySampleDao.class);
  1. 当我的接口 GenericDao 确实声明了方法并且由我的类 CriteriaQuerySampleDao 实现时:

    在这种情况下,按照下面的代码

  2. ,我的类不会在spring的应用程序上下文中加载
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));

    }

}

2 个答案:

答案 0 :(得分:0)

如果在构建时将代码覆盖工具(例如jacoco)连接到JVM,则会发生这种情况。它创建了一个Proxy类来处理覆盖范围,并且该Proxy类实现了您的接口,因此,虽然它是您接口的一个实例,但实际上并不是您Impl的一个实例。

答案 1 :(得分:0)

它与生成代理接口以启用事务支持的方式有关。您可以通过将SectionModel的{​​{1}}属性设置为proxyTargetClass来更改行为:

@EnableTransactionManagement

另请参见https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/transaction/annotation/EnableTransactionManagement.html#proxyTargetClass--

其背后的原因是true是通过decorator pattern与动态生成的装饰器类一起实现的。

Spring可以通过两种方式创建动态装饰器:default java proxies或CGLib。只能为实现接口的类生成默认的Java代理。对于@EnableTransactionManagement(proxyTargetClass= true) @ComponentScan @Component(value= "LocalHibernateConfig") public class LocalHibernateConfig { } ,它实现了一个接口,因此Spring将诉诸于默认的Java代理。