这个问题在这里已有答案:
我在application.yml
文件中有一些业务逻辑属性。
它们通过@ConfigurationProperties
注释类加载到应用程序中。
我怎么能在不是Spring Bean的类中使用这些属性?它不能是单例,因为它必须在运行时创建它的许多对象。
business.foo: 2
@ConfigurationProperties("business")
@Getter // lombok
@Setter // lombok
public class BusinessProperties {
private int foo;
}
@Component
public class TypicalBean {
private final BusinessProperties properties;
@Autowired
public TypicalBean(BusinessProperties properties) {
this.properties = properties;
}
@PostConstruct
public void printFoo() {
System.out.println("Foo: " + properties.getFoo()); // "Foo: 2"
}
}
public class NonBean {
public void printFoo() {
System.out.println("Foo: ???"); // How to access the property?
}
}
有没有办法创建一个非单例类,可以访问配置(甚至其他Spring bean),但其他工作方式与普通的java类相同?这意味着我可以控制它的创建,如果不再使用,它将由垃圾收集器收集,等等。
所有spring-beans都是由SpringApplicationContext创建的。 Bean - 它是简单的POJO对象,但是由Spring创建并保存在他的容器中。如果您想从容器外部访问bean - 请参阅:
Spring bean实际上是在应用程序上下文中使用,但是您可以通过将属性自动装配到Spring bean中的静态字段来实现您想要的。
@Component
public class BusinessPropertiesUtils {
public static BusinessProperties INSTANCE;
@Autowired
public setBusinessProperties(BusinessProperties properties) {
this.INSTANCE = properties;
}
}
然后:
public class NonBean {
public void printFoo() {
System.out.println("Foo: " + BusinessPropertiesUtils.INSTANCE.getFoo());
}
}
PS:这非常hacky,绝对不是“春天的方式”。
您可以使用prototype scope配置bean,每次请求时都会为您提供bean的新实例。从Spring文档:
与其他范围相比,Spring不管理原型bean的完整生命周期。容器实例化,配置和组装原型对象并将其交给客户端,而没有该原型实例的进一步记录。 ... 在某些方面,Spring容器关于原型范围bean的角色是Java new运算符的替代品。超过该点的所有生命周期管理必须由客户端处理。
如何将TypicalBean类转换为原型范围bean的示例:
@Component
@Scope("prototype")
public class TypicalBean {
...
}
另一种方法是手动实例化bean类(或任何POJO)并通过构造函数或setter方法注入依赖项(配置,spring bean等),如果它们可用或者可以从Spring Context获取它们。
new TypicalBean(properties);
您仍然可以将NonBean.class
定义为具有Scope.Prototype的Component
@Component
@Scope(value = BeanDefinition.SCOPE_PROTOTYPE)
public class NonBean {
@Autowired
public TypicalBean(BusinessProperties properties) {
this.properties = properties;
}
public void printFoo() {
System.out.println("Foo: " + properties.getFoo());
}
}
诀窍是如何创建NonBean.class
的实例。在你将要创建NonBean.class
实例的代码中,使用Spring的ObjectFactory<T>
private final ObjectFactory<NonBean> nonBeanFactory;
...
NonBean nonBean = nonBeanFactory.getObject();
实例化的nonBean
对象将自动装配。