我有一个类(ABC 类),它是通过调用构造函数来实例化的。 ABC 类又具有使用自动连接注入的辅助类(XYZ 类)。
我们的应用程序是基于 Spring MVC 的应用程序,我在服务器启动时没有看到任何异常。
但我仍然看到 XYZ 类为空。是因为ABC类没有被Spring容器实例化吗?
在这种情况下,如何利用自动连线?
谢谢。
您可以通过这种方式在非spring bean类中使用spring bean
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你可以得到像这样的spring bean对象:
ApplicationContext appCtx = ApplicationContextUtils.getApplicationContext();
String strFromContext = appCtx.getBean(beanName, String.class);
自动装配不起作用,因为 ABC 类不是由 Spring 管理的。您可以通过在类定义上方使用 @Component 注释(@Component、@Service、@Controller 等)之一来让 Spring 管理 ABC,然后在应用程序上下文 XML 中使用 context:component-scan,或者采用老方法只需直接在应用程序上下文中定义 bean 即可。
如果由于某种原因你无法让 Spring 管理类 ABC,你可以使用以下方法加载 ABC 中的应用程序上下文:
ApplicationContext 上下文 = 新 ClassPathXmlApplicationContext("path/to/applicationContext.xml");
然后使用:
XYZ someXyz = (XYZ) context.getBean("MyXYZ");
手动设置bean值。
正确:你不能只在课堂上拨打
new
并将其全部连接起来; Spring 必须管理 bean 才能发挥其所有魔力。
如果您可以发布有关您的用例的更多详细信息,我们也许可以建议有用的选项。
您可以在要自动装配其他bean的类中使用Spring的@Configurable注释。 此外,您需要使用 @EnableSpringConfigured 注释任何配置 bean,以便 Spring 知道您的可配置 bean。
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
...
}
}
对于像我这样有基本 Spring Boot 且不熟悉行话的菜鸟:
Ashish 的 answer 对我有用,但是 这篇文章 在我看来提供了更多解释。
如果您不知道所需 bean 的名称,请尝试在该数组中查找:
String[] names = context.getBeanDefinitionNames();
如果您对“组件扫描”和配置文件的讨论感到困惑,那么了解 @SpringBootApplication 注释(您可能会在 main() 方法附近找到)隐式调用 @Configuration 和 @ComponentScan 可能会有所帮助。
这意味着该包中的所有文件(在主类顶部声明)都由 Spring 拾取,并且您想要添加的任何 bean 都可以与 main() 一起编写
简而言之,是的,ABC 不会被注入 XYZ,因为 Spring 不管理 ABC。 Spring 无法配置它不知道的对象。
您可以通过用
@Service
或 @Component
注释来管理 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-using-aspectj
您可以使用
ABC
注释来注释 @Configurable
类。然后 Spring IOC 会将 XYZ
实例注入 ABC
类。它通常与 AspectJ AnnotationBeanConfigurerAspect
一起使用。
Spring 有 util 类
BeanUtils.instantiateClass(clazz)
BeanUtils.instantiate(clazz)
YouClass ins = BeanUtils.instantiate(YouClass.class)
另一种选择可能是获取启动类中的上下文(通常是
Application
)并将其保存在那里:
public class Application {
public static ApplicationContext context;
public static void main(String[] args) {
context = SpringApplication.run(Application.class, args);
}
}
然后你可以使用以下方法从任何地方获取 bean
Application.context.getBean("MyXYZ")
或类似
针对@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");