简体   繁体   English

为什么只在Spring Application Context中为Bean加载接口

[英]Why interface only for Bean loading in Spring Application Context

I was trying to load a class in application context which implements an interface, I encountered two situations 我试图在实现接口的应用程序上下文中加载一个类,我遇到了两种情况

  1. When interface GenericDao don't have any declared method: Here in this case my class CriteriaQuerySampleDao loads as per below code in application context there is no issue 当接口GenericDao没有任何声明的方法时:在这种情况下我的类CriteriaQuerySampleDao在应用程序上下文中按照下面的代码加载没有问题
CriteriaQuerySampleDao dao= context.getBean(CriteriaQuerySampleDao.class);
  1. When my interface GenericDao do have declared method and which is implemented by my class CriteriaQuerySampleDao : 当我的接口GenericDao确实已经声明了方法并且由我的类CriteriaQuerySampleDao实现时

    Here in this case my class don't get loaded in application context of spring as per below code 在这种情况下,我的类不会被加载到spring的应用程序上下文中,如下面的代码所示

CriteriaQuerySampleDao dao= context.getBean(CriteriaQuerySampleDao.class);

and throws 并投掷

Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.journaldev.spring.config.CriteriaQuerySampleDao' available

but when I load it by below code which is using interface GenericDao of my class CriteriaQuerySampleDao it loads successfully asper below code 但是当我通过使用我的类CriteriaQuerySampleDao的接口GenericDao的代码加载它时,它会在代码下面成功加载asper

GenericDao dao= context.getBean(GenericDao.class);

can some one explain why I am forced to load CriteriaQuerySampleDao class by GenericDao interface if my class is implementing aeven a single method of interface. 有人可以解释为什么我被迫通过GenericDao接口加载CriteriaQuerySampleDao类,如果我的类正在实现一个单一的接口方法。

I am not sure about details, is it custom in spring? 我不确定细节,春天有定制吗?

GenericDao Interface GenericDao接口

interface GenericDao<T>
{

    Session getSession();

    Class<T> getDefaultMappedObject();
}

CriteriaQuerySampleDao Class implementing GenericDao 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 Class Configuration And Class Having Main Method: 具有主要方法的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));

    }

}

This will happen if you have a code coverage tool, like jacoco, attached to the JVM when building. 如果您在构建时附加到JVM的代码覆盖工具(如jacoco),则会发生这种情况。 It creates a Proxy class to handle the coverage, and that Proxy class implements your interface, so while its an instance of your interface, its not actually an instance of your Impl. 它创建了一个Proxy类来处理覆盖范围,而Proxy类实现了你的接口,所以虽然它是你的接口实例,但它实际上并不是你的Impl实例。

It is related to the way proxy interfaces are generated for enabling transaction support. 它与生成代理接口以启用事务支持的方式有关。 You can change the behavior by setting the proxyTargetClass attribute of the @EnableTransactionManagement to true : 您可以通过设置更改行为proxyTargetClass的属性@EnableTransactionManagementtrue

@EnableTransactionManagement(proxyTargetClass= true)
@ComponentScan
@Component(value= "LocalHibernateConfig")
public class LocalHibernateConfig {

}

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

The reason behind this is that @EnableTransactionManagement is implemented using the decorator pattern with dynamically generated decorator classes. 这背后的原因是@EnableTransactionManagement是使用动态生成的装饰器类的装饰器模式实现的。

Spring can create the dynamic decorator in two ways, default java proxies or CGLib. Spring可以通过两种方式创建动态装饰器, 默认的Java代理或CGLib。 Default java proxies can only be generated for classes that implement an interface. 只能为实现接口的类生成默认的Java代理。 In the case of CriteriaQuerySampleDao it implements an interface so Spring will resort to a default java proxy. CriteriaQuerySampleDao的情况下,它实现了一个接口,因此Spring将使用默认的Java代理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM