弹簧自动装配不能从非弹簧管理类工作

时间:2013-08-21 01:31:48

标签: spring spring-mvc tomcat

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

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

但我仍然认为Class XYZ为null。是因为类ABC不是由Spring容器实例化的吗?

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

感谢。

10 个答案:

答案 0 :(得分:21)

您可以使用这种方式在非spring bean类

中使用spring bean
    public class ApplicationContextUtils implements ApplicationContextAware {

  private static ApplicationContext ctx;

  @Override
  public void setApplicationContext(ApplicationContext appContext)
      throws BeansException {
    ctx = appContext;

  }

  public static ApplicationContext getApplicationContext() {
    return ctx;
  }
}

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

来自applicationcontext的

你可以得到像这样的spring bean对象:

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

答案 1 :(得分:7)

自动装配不起作用,因为ABC不管理类。您可以通过在类定义上方使用@Component注释(@ Component,@ Service,@ Controller等)之一来使Spring管理ABC,然后在应用程序上下文XML中使用context:component-scan,或者去旧学校和只需在应用程序上下文中直接定义bean。

如果由于某种原因你不能使Spring管理类ABC,你可以使用类似的东西在ABC中加载应用程序上下文:

  

ApplicationContext context = new   的ClassPathXmlApplicationContext( “路径/到/ applicationContext.xml中”);

然后使用:

  

XYZ someXyz =(XYZ)context.getBean(“MyXYZ”);

手动设置bean值。

答案 2 :(得分:3)

正确:你不能只在课堂上打电话给new并把它全部搞定; Spring必须管理bean才能完成所有的魔法。

如果您可以发布有关用例的更多详细信息,我们可能会建议有用的选项。

答案 3 :(得分:3)

您可以在要自动装配其他bean的类中使用Spring的@Configurable批注。 此外,您需要使用@EnableSpringConfigured注释任何配置bean,以便Spring知道您的可配置bean。

@EnableSpringConfigured documentation

  

public @interface EnableSpringConfigured   发信号通知当前应用程序上下文,以将依赖项注入应用于在Spring bean工厂外部实例化的非托管类(通常使用@Configurable注释注释的类)。   与Spring的XML元素中的功能类似。通常与@EnableLoadTimeWeaving一起使用。

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

答案 4 :(得分:1)

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

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

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

答案 5 :(得分:1)

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

答案 6 :(得分:0)

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

答案 7 :(得分:0)

对于像我这样的新手,他们做基本的Spring Boot并且不熟悉行话:

  • 您的服务,回购协议等都是Bean
  • 您可以从ApplicationContext获取Beans

Ashish的answer对我有用,但是this article为imo提供了更多解释。

如果您不知道想要的bean的名称,请尝试查找此数组:

String[] names = context.getBeanDefinitionNames();

如果您对“组件扫描”和配置文件的讨论感到困惑,那么可能会知道@SpringBootApplication批注(可以在main()方法附近找到)会隐式调用@Configuration和@ComponentScan。

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

答案 8 :(得分:0)

在回应@Ashish Chaurasia提供的答案时,谨提及该解决方案是不完整的。类ApplicationContextUtils也应该是spring bean,以便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");

答案 9 :(得分:0)

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