- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我有一个原型(prototype)范围的bean,我想通过@Autowired 注解注入(inject)它。在这个 bean 中,还有 @PostConstruct 方法,它没有被 Spring 调用,我不明白为什么。
我的 bean 定义:
package somepackage;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
@Scope("prototype")
public class SomeBean {
public SomeBean(String arg) {
System.out.println("Constructor called, arg: " + arg);
}
@PostConstruct
private void init() {
System.out.println("Post construct called");
}
}
我要注入(inject) bean 的 JUnit 类:
package somepackage;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@ContextConfiguration("classpath*:applicationContext-test.xml")
public class SomeBeanTest {
@Autowired
ApplicationContext ctx;
@Autowired
@Value("1")
private SomeBean someBean;
private SomeBean someBean2;
@Before
public void setUp() throws Exception {
someBean2 = ctx.getBean(SomeBean.class, "2");
}
@Test
public void test() {
System.out.println("test");
}
}
Spring 配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="somepackage"/>
</beans>
执行的输出:
Constructor called, arg: 1
Constructor called, arg: 2
Post construct called
test
当我通过从 ApplicationContext
调用 getBean
来初始化 bean 时,一切都按预期工作。我的问题是为什么通过 @Autowire
和 @Value
组合注入(inject) bean 不调用 @PostConstruct
方法
最佳答案
为什么使用@Value 而不是@Autowired?
@Value
注释用于注入(inject)值,通常作为目标字符串、原语、装箱类型和 java 集合。
The @Value annotation can be placed on fields, methods and method/constructor parameters to specify a default value.
Value
接收一个字符串表达式,spring 使用它来处理到目标对象的转换。这种转换可以通过Spring's type conversion , java bean property editor ,以及 Spring's SpEL expresions .原则上,这种转换的结果对象不由 spring 管理(即使您可以从任何这种方法返回一个已经管理的 bean)。
另一方面,AutowiredAnnotationBeanPostProcessor是一个
BeanPostProcessor implementation that autowires annotated fields, setter methods and arbitrary config methods. Such members to be injected are detected through a Java 5 annotation: by default, Spring's @Autowired and @Value annotations.
该类处理字段注入(inject),解析依赖,最终调用方法doResolveDependency , 是在解决注入(inject)的“优先级”的这个方法中,springs 检查是否存在通常是表达式字符串的建议值,这个建议值是注释 Value
的内容,所以如果存在,则调用类 SimpleTypeConverter已完成,否则 spring 会寻找候选 bean 并解析 Autowiring 。
@Autowired
被忽略而使用@Value
的原因仅仅是因为首先检查了 value 的注入(inject)策略。显然总是要优先考虑,当使用多个冲突的注解时,spring 也可能会抛出异常,但在这种情况下,是由先前对 sugested 值的检查确定的。
我找不到任何与这个“优先级”相关的东西是 spring,但简单是因为不打算一起使用这个注解,就像它不打算使用 @Autowired
和 @Resource
一起。
@Value 为什么会创建对象的新实例
前面说过类SimpleTypeConverter
是在建议值出现的时候调用的,具体调用的是方法convertIfNecessary ,这是执行将字符串转换为目标对象的方法,同样可以使用属性编辑器或自定义转换器来完成,但这里没有使用这些。也不使用 SpEL 表达式,仅使用字符串文字。
Spring首先检查目标对象是字符串还是集合/数组(可以转换例如逗号分隔的列表),然后检查目标是否是枚举,如果是,它会尝试转换字符串,如果是不是,不是接口(interface)而是类,它检查 Constructor(String)
的存在以最终创建对象(不由 spring 管理)。基本上,这个转换器尝试了许多不同的方法来将字符串转换为最终的对象。
此实例化只能使用字符串作为参数,例如,如果您使用 SpEL 表达式来返回长 @Value("#{2L}")
,并使用带有一个 Constructor(Long)
它将抛出一个带有类似消息的 IllegalStateException
:
Cannot convert value of type 'java.lang.Long' to required type 'com.fiberg.test.springboot.object.Hut': no matching editors or conversion strategy found
可能的解决方案
使用简单的@Configuration 类作为供应商。
public class MyBean {
public MyBean(String myArg) { /* ... */ }
// ...
@PostConstruct public init() { /* ... */ }
}
@Configuration
public class MyBeanSupplier {
@Lazy
@Scope(scopeName = ConfigurableBeanFactory.SCOPE_PROTOTYPE,
proxyMode = ScopedProxyMode.NO)
public MyBean getMyBean(String myArg) {
return new MyBean(myArg);
}
}
您可以将 MyBean 定义为 MyBeanSupplier 类中的静态类,如果它是唯一的方法。此外,您不能使用代理模式 ScopedProxyMode.TARGET_CLASS,因为您需要将参数作为 bean 提供,而传递给 getMyBean
的参数将被忽略。
使用这种方法,您将无法 Autowiring bean 本身,而是 Autowiring 供应商,然后调用 get 方法。
// ...
public class SomeBeanTest {
@Autowired private MyBeanSupplier supplier;
// ...
public void setUp() throws Exception {
someBean = supplier.getMyBean("2");
}
}
您还可以使用应用程序上下文创建 bean。
someBean = ctx.getBean(SomeBean.class, "2");
而且@PostConstruct
方法不管你用哪一个都应该被调用,但是@PreDestroy
is not called in prototype beans .
关于java - 为什么使用构造函数参数 Autowiring 原型(prototype)bean时不调用@PostConstruct方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49007559/
有什么区别 和 您能解释一下这两者之间有什么区别吗? 最佳答案 它是一个 XML 命名空间,用于分隔可能存在冲突的元素名称,因此没有真正的区别。 XML Namespaces 关于java -
我刚刚浏览了两个 Web 应用程序,在两个项目的“applicationContext.xml”文件中都有一个标记 ... 另一个是 ... 谁能给我解释一下有什么区别吗? 最佳答案 没有语
我一直在尝试了解 WebSphere Commerce 中的 Java bean,但我真的很困惑。请帮帮我。我需要知道: What is the difference between EntityBe
自从我们更新到 grails 2.0.1(从 2.0.0 开始)以来,通过 bean 字段显示的所有 bean 都错误地显示为“withBean”字段的第一个属性。在我下面发布的示例中,所有 [fir
我有一个 bean,我将另一个 beanlist 放入其中,并且我想访问该内部 bean。 我的第一个 Bean 是: public class FirstDTO { private String F
我正在尝试将 CSS 和 JS 添加到 spring MVC 项目中的 JSP 页面,以便我在 dispatcher-servlet.xml 中包含了 js/css 文件夹的引用,如下所示:
当我将请求传递给 RestController 时,出现以下错误。 org.springframework.beans.factory.xml.XmlBeanDefinitionStoreExcept
我看到很多示例将 bean 标记为实体 bean (@Entity) 和命名 bean (CDI),以避免创建 2 个类(托管 bean 和实体 bean)并利用 Bean 验证以便可以执行验证在客户
在我的理解中, session 总是意味着有状态。考虑 servlet session 对象, 想想 cookie。如果 session 是无状态的,我认为我们根本不需要 session 。 在jee
我完全是Spring框架的初学者。我当时正在玩一个创建对象实例的示例。因此需要您的帮助! 看看这个例子: MainApp.java: import org.springframework.contex
这个问题在这里已经有了答案: What is a JavaBean exactly? (23 个回答) 关闭 7 年前。 我已经阅读了有关 EJB、Java Beans 的内容,但是我仍然对“bea
我刚开始使用 Spring-Framework,实际上我正在使用 spring-boot 库。我有以下问题: 我知道在 @Configuration 类中使用 @Bean 注册的 bean 默认是单例
我对下面提到的场景中使用Spring Framework时会创建的实例数量有疑问: bean配置是这样的 or 默认情况下,bean "a"有 singleton scope .所以
在我的 Spring-Module.xml 中,我有两个 bean: ... ... 我像这样实例化我的类: Applicat
@Autowired private Map departments; 我的 spring 配置文件 只要使用 @Autowired 需要日期,它就可以正常工作 同样, 如何使用没有属性
我已经为 ComboBox 设置了 ContainerDataSource this.comboBox.setContainerDataSource(container)。这个容器是一个 BeanIt
为了支持流畅的编程风格,我最近修改了我们的 Java Beans setter 方法以返回 Bean 类。但是现在 Java Beans Activation Framework (rel 1.1)
有人可以告诉我在我的 ApplicationContext 中我必须使用 beans:bean 而不是 bean 的什么以及如何修复它。
我有如下配置: batch:job id="reconciliationJob" job-repository="jobRepository" restartable="true" 在应用程序上下文启
我已经为 Test_flow 创建了简单的测试套件,但是当我尝试运行该流程时出现错误。 java.lang.RuntimeException: org.mule.api.config.Configur
我是一名优秀的程序员,十分优秀!