java - 如果没有自动完成,如何手动注入(inject) Spring 注入(inject)

标签 java hibernate spring

我的 spring 依赖项工作正常但是有一个类

CustomUserDetaisls 我需要名为 Autowired 的依赖项

@Autowired Private UserDAO userDAO

匹配用户名和密码

但是我的 spring 注入(inject)在这里不起作用,因为这个类实现了 userDetailsS​​erivce 。但是,如果我移除工具,注入(inject)就会起作用。

我已经在 this question 中提交了问为什么的问题,但没有人给我答案,所以我决定使用带有新操作符的 DAO

private UserDAO userDAO = new UserDAO();

但是 userDAO 又依赖于 session Factory,它是一个 spring bean。

然后我再次决定从 java 代码获取 sessionfactory 而不是使用以下代码的 spring

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

但是我在 hibernate-context 中有几个 bean,比如数据源、属性文件,我发现很难重写所有的东西。

有什么方法可以手动注入(inject) userDAO 以便所有相关的 spring 注入(inject)(如 sessionFactories)工作

最佳答案

如果您有权访问 spring 上下文,则可以检索一个 AutowireCapableBeanFactory,然后您可以像这样在任何 bean 上使用它:

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"); 

但是,如果一个 bean 需要在使用前 Autowiring ,我更喜欢使用第一种机制并将构造函数标记为私有(private)/ protected ,以确保它不能通过“new”创建并强制它通过上述工厂创建。

2017 年 11 月 27 日更新

我个人不喜欢每次创建 Autowiring 实例时都必须使用工厂。特别是如果一些其他进程正在创建实例,例如从数据库反序列化等。

我最终创建了一个方面来自动处理 Autowiring 。

首先,我创建了一个注解来标记我希望 Autowiring 的类:

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

然后我创建了一个方面,它使用“构建后”切点来进行 Autowiring 。不幸的是,我无法找出仅在“最后一个”构造函数完成后才调用的切点,但多次 Autowiring 似乎并没有什么坏处,至少在我的情况下是这样。

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"/>

现在我可以创建任何实例并通过附加注释使其 Autowiring :

@AutowireAfterCreation
public class TestEntity {

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

    @Autowired
    private TestRepository repository;

}

最后,您所要做的就是创建一个实例,它会在构造函数完成后自动 Autowiring :

TestEntity entity = new TestEntity();

2018 年 1 月 2 日更新

接口(interface)ApplicationContext变了,去掉了get(),但是仍然可以使用第一种机制,只是需要调用getAutowireCapableBeanFactory()来代替。

因此,此答案顶部示例中的前两行现在如下所示:

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

关于java - 如果没有自动完成,如何手动注入(inject) Spring 注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5450073/

相关文章:

Java Eclipse : How to view Compile warnings

java - jasper 报告 - 如何向条形码数字输出添加星号?

java - 将 Varchar 列类型映射到实体 jpa 中的 Integer

Java spring boot 延迟获取和 json 忽略不起作用

java - 无法使用 ResourceBundleMessageSource 查找消息

java - JMF使用javax.imageio问题

java - 使用字段对类的 Arraylist 进行排序

java - 如何让 @ExceptionHandlers 在默认为任何运行时错误的异常处理程序之前处理特定异常?

java - JPA 设置引用的属性而不检索它。最佳实践

java - IntelliJ : How to enable JPAQL validation without persistence. XML?