spring自动布线无法从非spring托管类中工作



我有一个类(class ABC),它是通过调用构造函数实例化的。类ABC又有一个使用自动连线注入的辅助类(类XYZ)。

我们的是一个基于Spring MVC的应用程序,在服务器启动时我没有看到任何异常。

但我仍然认为XYZ班是空的。是因为Spring Container没有实例化类ABC吗?

在这种情况下,我如何利用自动布线?

谢谢。

您可以使用这种方式在非springbean类中使用springbean

import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class ApplicationContextUtils implements ApplicationContextAware {
     
      private static ApplicationContext ctx;
     
      @Override
      public void setApplicationContext(ApplicationContext appContext) {
        ctx = appContext;
      }
     
      public static ApplicationContext getApplicationContext() {
        return ctx;
      }
}

现在您可以通过getApplicationContext()这个方法获取applicationcontext对象。

从applicationcontext中,您可以获得如下springbean对象:

ApplicationContext appCtx = ApplicationContextUtils.getApplicationContext();
String strFromContext = appCtx.getBean(beanName, String.class);

自动布线无法工作,因为类ABC不由Spring管理。您可以使用类定义之上的@Component注释(@Component、@Service、@Controller等)之一,然后在应用程序上下文XML中使用context:Component扫描,使Spring管理ABC,或者老派,直接在应用程序环境中定义bean。

如果由于某种原因,您无法使Spring管理类ABC,则可以使用以下方法在ABC中加载应用程序上下文:

ApplicationContext context=新建ClassPathXmlApplicationContext("path/to/applicationContext.xml");

然后使用:

XYZ someXyz=(XYZ)context.getBean("MyXYZ");

手动设置bean值。

正确:不能只在类上调用new并将其全部连接起来;Spring必须管理bean才能发挥其所有的魔力。

如果你能发布更多关于你的用例的细节,我们可能会提出有用的选项。

您可以在想要自动连接其他bean的类中使用Spring的@ConfigurationAnnotation。此外,您还需要使用@EnableSpringConfigured对任何配置bean进行注释,以便Spring了解您的可配置bean。

@EnableSpringConfigured文档

public@interface EnableSpringConfigured向当前应用程序上下文发出信号,以将依赖项注入应用于在Spring bean工厂之外实例化的非托管类(通常是用@Configurationannotation注释的类)。类似于Spring的XML元素中的功能。经常与@EnableLoadTimeWiving结合使用。

@Configurable(autowire = Autowire.BY_TYPE)
public class ABC {
    @Autowire private XYZ xyz;
    ...
}
@Configuration
@EnableSpringConfigured
public class Application {
    ...
}
public class MyClass {
    public void doSomething() {
        ABC abc = new ABC(); // XYZ is successfully autowired
        ...
    }
}

对于像我这样做基本Spring Boot但不熟悉行话的人来说:

  • 你的服务、回购等都是豆子
  • 您可以从ApplicationContext获取Beans

Ashish的答案对我有效,但这篇文章提供了更多的解释。

如果你不知道你想要的bean的名称,试着在这个数组中查找:

String[] names = context.getBeanDefinitionNames();

如果你对"组件扫描"和配置文件的说法感到困惑,那么了解@SpringBootApplication注释(你可能会在main()方法附近找到)隐式调用@Configuration和@ComponentScan可能会有所帮助。

这意味着该包中的所有文件(在主类顶部声明)都由Spring提取,并且您想要添加的任何bean都可以与main()一起写入

简而言之,是的,ABC没有被注入XYZ,因为Spring没有管理ABC。Spring无法配置它不知道的对象。

您可以通过用@Service@Component对ABC进行注释来管理ABC。请注意,为了让Spring了解这些注释,Spring必须启用自动扫描:

<context:component-scan base-package="com.mypackage.awesomeproject" />

第一个问题-是的,您有null,因为类不是用spring启动的第二个问题-我认为你可以使用aspectj支持http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/aop.html#aop-使用aspectj

您可以使用@Configurable注释来注释ABC类。然后Spring IOC会将XYZ实例注入到ABC类中。它通常与AspectJ AnnotationBeanConfigurerAspect一起使用。

Spring具有util类

 BeanUtils.instantiateClass(clazz)
 BeanUtils.instantiate(clazz)
 YouClass ins = BeanUtils.instantiate(YouClass.class)

https://docs.spring.io/autorepo/docs/spring/4.0.2.RELEASE/javadoc-api/org/springframework/beans/BeanUtils.html

在回答@Ashish Chaurasia提供的答案时,我想指出解决方案是部分的。类ApplicationContextUtils也应该是springbean,以便spring调用以下代码。

if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(ctx); 
}

位于类顶部的@Component将使解决方案变得完整。此外,还有一种使用@Autowired注释进行此操作的替代方法。

@Component
public class ApplicationContextProvider {
    private static ApplicationContext context;
    public static ApplicationContext getApplicationContext() {
        return context;
    }
    @Autowired
    public void setContext(ApplicationContext context) {
        ApplicationContextProvider.context = context;
    }
}

getBean方法现在可以通过-轻松访问

ApplicationContextProvider.getApplicationContext().getBean("myBean");

最新更新