java 如果没有自动完成,如何手动注射弹簧注射

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5450073/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 11:11:20  来源:igfitidea点击:

How to inject spring injection manually if not done automatically

javahibernatespring

提问by slayer_b

My spring dependencies are working fine but there one class

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

CustomUserDetaislswhere i need the Autowired dependency called

CustomUserDetaisls我需要自动装配依赖项的地方

@Autowired Private UserDAO userDAO

to match with username and password

匹配用户名和密码

But my spring injection is not working here as this class implements the userDetailsSerivce. However injection works if i remove the implements.

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

I have submitted the question to ask why in this question, but no one gave me answer so i decided to use the DAO with new operator

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

private UserDAO userDAO = new UserDAO();

But that userDAOin turn depends on session Factory which is a spring bean.

但这userDAO反过来又取决于 session Factory,它是一个 spring bean。

Then i again decided to get sessionfactory from java code rather than spring using following code

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

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

But again i have several bean in hibernate-context like datasource , properties file and i am finding it very hard to re-write all the things.

但是我在 hibernate-context 中有几个 bean,比如 datasource ,properties 文件,我发现很难重写所有的东西。

Is there any way that I can manually inject userDAOso that all the related spring injection like sessionFactories works

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

回答by DavidA

If you have access to the spring context, you can retrieve an AutowireCapableBeanFactory which you can then use on any bean like this:

如果您有权访问 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"); 

However, if a bean requires that it be autowired before it can be used, I prefer to use the first mechanism and mark the constructor as private/protected to make sure that it cannot be created via 'new' and force it to be created via a factory like above.

但是,如果 bean 需要在使用前自动装配,我更喜欢使用第一种机制并将构造函数标记为私有/受保护以确保它不能通过“new”创建并强制通过像上面这样的工厂。

UPDATE 11/27/17

更新 11/27/17

I personally didn't like to have to use the factory every time I wanted to create an autowired instance. Particularly if some other process was creating the instance, such as deserializing from a database, etc.

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

I ended up creating a aspect to automatically handle the autowiring.

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

First, I created an annotation to flag classes that I wanted automatically autowired:

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

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

Then I created an aspect that uses an 'after construction' point cut to do the autowiring. Unfortunately, I was unable to figure out a point cut that was only called after the 'last' constructor was finished, but it doesn't seem to hurt to autowire multiple times, at least in my case.

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

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

Then I had to tell Spring about the aspect so the factoryBean is autowired into the aspect itself:

然后我不得不告诉 Spring 有关方面的信息,以便 factoryBean 自动装配到方面本身:

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

Now I can create any instance and have it automatically autowired simply by attaching the annotation:

现在我可以创建任何实例并通过附加注释让它自动自动装配:

@AutowireAfterCreation
public class TestEntity {

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

    @Autowired
    private TestRepository repository;

}

Finally, all you have to do is create an instance, and it is automatically autowired after the completion of the constructors:

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

TestEntity entity = new TestEntity();

UPDATE 1/2/2018

更新 1/2/2018

The interface ApplicationContext has changed, and get() has been removed, but you can still use the first mechanism, but you need to call getAutowireCapableBeanFactory() instead.

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

So the first two lines in the example at the top for this answer would now look like:

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

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

回答by slayer_b

You can take a look at spring java configuration. http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html#beans-java

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

In example below all dependencies of UserDAO will be automatically set by spring. It should be something like this:

在下面的示例中,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;
    }
}