Почему интерфейс только для загрузки Бина в контексте приложения Spring - PullRequest
3 голосов
/ 27 марта 2019

Я пытался загрузить класс в контексте приложения, который реализует интерфейс, я столкнулся с двумя ситуациями

  1. Когда интерфейс GenericDao не имеет никакого объявленного метода: здесь, вв этом случае мой класс CriteriaQuerySampleDao загружается в соответствии с приведенным ниже кодом в контексте приложения, нет проблемы
CriteriaQuerySampleDao dao= context.getBean(CriteriaQuerySampleDao.class);

Когда мой интерфейс GenericDao имеет объявленный метод и который реализован моим классом CriteriaQuerySampleDao :

Здесь, в этом случае, мой класс незагружаться в контексте приложения 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

, но когда я загружаю его с помощью кода ниже, который использует интерфейс GenericDaoмоего класса CriteriaQuerySampleDao успешно загружается, как показано ниже: код

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

может кто-нибудь объяснить, почему я вынужден загружать CriteriaQuerySampleDao класс с помощью интерфейса GenericDao , если мой классРеализация даже одного метода интерфейса.

Я не уверен в деталях, это весной?

GenericDao Interface

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 голосов
/ 27 марта 2019

Это связано с тем, как создаются прокси-интерфейсы для поддержки транзакций. Вы можете изменить поведение, установив атрибут proxyTargetClass для @EnableTransactionManagement в true:

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

}

Также см. https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/transaction/annotation/EnableTransactionManagement.html#proxyTargetClass--

Причина этого заключается в том, что @EnableTransactionManagement реализован с использованием шаблона декоратора с динамически генерируемыми классами декоратора.

Spring может создать динамический декоратор двумя способами: Java-прокси по умолчанию или CGLib. Java-прокси по умолчанию могут быть созданы только для классов, которые реализуют интерфейс. В случае CriteriaQuerySampleDao он реализует интерфейс, поэтому Spring будет использовать Java-прокси по умолчанию.

0 голосов
/ 27 марта 2019

Это произойдет, если у вас есть инструмент покрытия кода, такой как jacoco, подключенный к JVM при сборке. Он создает класс Proxy для обработки покрытия, и этот класс Proxy реализует ваш интерфейс, поэтому, хотя он является экземпляром вашего интерфейса, он фактически не является экземпляром вашего Impl.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...