Как ввести пружину вручную, если не сделано автоматически - PullRequest
1 голос
/ 27 марта 2011

Мои весенние зависимости работают нормально, но есть один класс

CustomUserDetaisls, где мне нужна зависимость Autowired с именем

@Autowired Private UserDAO userDAO

, чтобы соответствовать имени пользователя и паролю

Но мой весенний впрыск здесь не работает, так как этот класс реализует userDetailsSerivce.Однако инъекция работает, если я удаляю орудия.

Я задал вопрос, чтобы спросить, почему в этот вопрос , но никто не дал мне ответа, поэтому я решил использовать DAO с новым оператором

private UserDAO userDAO = new UserDAO();

Но это userDAO, в свою очередь, зависит от фабрики сессий, которая является пружинным бином.

Затем я снова решил получить сессионный завод из кода Java, а не из пружины, используя следующий код

SessionFactory sessionFactory = new AnnotationConfiguration()
        .configure("com/vaannila/service/hibernate.cfg.xml")
        .buildSessionFactory();

Но, опять же, у меня есть несколько bean-компонентов в hibernate-контексте, таких как источник данных, файл свойств, и мне очень трудно переписать все.

Есть ли способ, которым я могу вручнуювведите userDAO, чтобы все связанные пружинные инъекции, такие как sessionFactories, работали

Ответы [ 2 ]

5 голосов
/ 03 июня 2013

Если у вас есть доступ к контексту Spring, вы можете получить AutowireCapableBeanFactory, который затем сможете использовать с любым компонентом, подобным этому:

ApplicationContext springContext = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContextEvent.getServletContext());
AutowireCapableBeanFactory factory = springContext.get(AutowireCapableBeanFactory.class);

// this would instantiate and autowire a bean:
UserDAO userDAO = factory.createBean(UserDAO.class);

// this will autowire an already existing bean:
UserDAO manualUserDAO = new UserDAO();
factory.initializeBean(manualUserDAO, "beanNameIfNeeded"); 

Однако, если боб требует, чтобы он был автоматически подключен, прежде чем его можно будет использовать, я предпочитаю использовать первый механизм и помечать конструктор как закрытый / защищенный, чтобы убедиться, что он не может быть создан с помощью 'new', и принудительно заставить его быть создан через фабрику, как указано выше.

ОБНОВЛЕНИЕ 11/27/17

Мне лично не нравилось использовать фабрику каждый раз, когда я хотел создать экземпляр с автопроводкой. Особенно, если какой-то другой процесс создавал экземпляр, такой как десериализация из базы данных и т. Д.

Я закончил тем, что создал аспект для автоматической обработки автопроводки.

Во-первых, я создал аннотацию для пометки классов, которые я хотел автоматически подключать автоматически:

@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface AutowireAfterCreation {
}

Затем я создал аспект, в котором для выполнения автопроводки используется точка «после строительства». К сожалению, я не смог определить точечный разрез, который был вызван только после того, как был завершен «последний» конструктор, но, кажется, не повредит автоматическое связывание несколько раз, по крайней мере, в моем случае.

public aspect AutowiringAfterCreation {

    @Autowired
    private AutowireCapableBeanFactory beanFactory;

    /**
     * After construction, autowire the instance.
     * @param o Newly created object to be autowired.
     */
    after(Object o) returning : target(o) && initialization((@AutowireAfterCreation *).new(..)) {
        // this aspect will actually autowire the instance multiple times if the class is part of an inheritance
        // Hierarchy.  This is not optimal, but it should not hurt anything to autowire more than once.
        // FUTURE: modify the aspect so it only runs once, regardless of how many constructor calls are necessary.
        beanFactory.autowireBeanProperties(o, AutowireCapableBeanFactory.AUTOWIRE_NO, false);
        beanFactory.initializeBean(o, "unused");
    }   
}

Затем мне пришлось рассказать Spring об аспекте, чтобы factoryBean автоматически подключался к самому аспекту:

<bean class="AutowiringOnDemand" factory-method="aspectOf"/>

Теперь я могу создать любой экземпляр и автоматически подключить его, просто добавив аннотацию:

@AutowireAfterCreation
public class TestEntity {

    @Value("${some.config.value}")
    private String value;

    @Autowired
    private TestRepository repository;

}

Наконец, все, что вам нужно сделать, это создать экземпляр, и он автоматически подключается после завершения работы конструкторов:

TestEntity entity = new TestEntity();

ОБНОВЛЕНИЕ 1/2/2018

Интерфейс ApplicationContext изменился, и get () был удален, но вы все равно можете использовать первый механизм, но вместо этого вам нужно вызвать getAutowireCapableBeanFactory ().

Итак, первые две строки в примере сверху для этого ответа теперь будут выглядеть так:

ApplicationContext springContext = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContextEvent.getServletContext());
AutowireCapableBeanFactory factory = springContext.getAutowireCapableBeanFactory();
2 голосов
/ 13 декабря 2011

Вы можете взглянуть на конфигурацию Spring Java. http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html#beans-java

В приведенном ниже примере все зависимости UserDAO будут автоматически установлены пружиной. Должно быть что-то вроде этого:

@Configuration
@PropertySource("classpath:configuration.properties")
public class ApplicationConfig {
    @Bean
    public UserDAO userDAO() {
    return new UserDAO();
    }
    @Bean
    public CustomUserDetails customUserDetails (UserDAO userDAO) {
       CustomUserDetails customUserDetails = new CustomUserDetails ();
       customUserDetails.setUserDAO(userDAO());
       return customUserDetails;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...