【问题标题】:How to inject spring injection manually if not done automatically如果没有自动完成,如何手动注入弹簧注入
【发布时间】:2018-01-03 06:23:40
【问题描述】:

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

CustomUserDetaisls 我需要调用 Autowired 依赖项

@Autowired Private UserDAO userDAO

与用户名和密码匹配

但是我的 spring 注入在这里不起作用,因为这个类实现了 userDetailsSerivce 。但是,如果我移除工具,注射会起作用。

我已经在this question 中提交了问为什么的问题,但是没有人给我答案,所以我决定将 DAO 与 new operator 一起使用

private UserDAO userDAO = new UserDAO();

但是userDAO 又依赖于会话工厂,它是一个spring bean。

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

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

但是我在休眠上下文中有几个 bean,比如数据源、属性文件,我发现重写所有东西非常困难。

有什么方法可以手动注入userDAO,以便所有相关的弹簧注入,如 sessionFactories 工作

【问题讨论】:

  • 为什么字段类型是UserDAO ,而不是接口类型?
  • 我没有制作单独的接口然后实现。我只是使用 UserDAO 作为类
  • 在这种情况下,解决方案似乎很清楚 - 添加一个接口,并使用该类型来连接 bean。
  • 我试过我再次得到空指针异常

标签: java hibernate spring


【解决方案1】:

如果您可以访问 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 需要在使用之前自动装配,我更喜欢使用第一种机制并将构造函数标记为私有/受保护,以确保它不能通过“new”创建并强制它通过像上面这样的工厂创建。

2017 年 11 月 27 日更新

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

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

首先,我创建了一个注释来标记我希望自动装配的类:

@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();

2018 年 1 月 2 日更新

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

因此,该答案顶部示例中的前两行现在看起来像:

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

【讨论】:

【解决方案2】:

你可以看看spring java的配置。 http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html#beans-java

在下面的示例中,UserDAO 的所有依赖项都将由 spring 自动设置。 应该是这样的:

@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;
    }
}

【讨论】:

    猜你喜欢
    • 2018-03-13
    • 2012-12-06
    • 2011-08-09
    • 1970-01-01
    • 2017-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-04
    相关资源
    最近更新 更多