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");
}
}
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");
}
}
<?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
组合注入bean不调用@postconstruct
方法
为什么使用@value而不是@autowired?
@value
注释用于注入值,通常有目标字符串、原语、装箱类型和java集合。
根据Spring的文档:
BeanPostProcessor实现,它可以自动读取带注释的字段、setter方法和任意配置方法。这些要注入的成员是通过Java5注释检测的:默认情况下,Spring的@autowired和@value注释。
该类处理字段注入,解析依赖项,并最终调用方法doResolveDependency。在此方法中,解析注入的“优先级”,springs检查是否存在一个sugest值,该值通常是表达式字符串,该sugest值是注释值
的内容,因此如果存在,就调用SimpleTypeConverter类,否则spring查找candicate bean并解析autowire。
忽略@autowired
而使用@value
的原因很简单,因为首先检查了value的注入策略。显然spring必须始终是优先级,当使用多个冲突的注释时spring也可能引发异常,但在这种情况下是由前面对sugested值的检查决定的。
我找不到任何与这个“优先级”有关的东西,is spring,但是simple是因为它不打算一起使用这个注释,就像它也不打算一起使用@autowired
和@resource
一样。
为什么@value创建对象的新意图
前面我说过,当建议的值出现时调用类SimpleTypeConverter
,具体的调用是对ConvertifMedial方法的调用,该方法执行将字符串转换为目标对象的操作,同样,这可以使用属性编辑器或自定义转换器来完成,但这里没有使用这些方法。SpEL表达式也没有使用,只是一个字符串。
Spring首先检查目标对象是否是字符串或集合/数组(可以转换例如逗号分隔的列表),然后检查目标对象是否是枚举,如果是,它尝试转换字符串,如果不是,并且不是接口而是类,它检查构造函数(string)
的存在,最终创建对象(不由Spring管理)。基本上,这个转换器尝试了许多不同的方法将字符串转换为最终对象。
如果您使用SpEL表达式返回长@value(“#{2L}”)
,并且使用带有构造函数(long)
的对象,则该实例化将只使用字符串作为参数,它将抛出具有类似消息的IllegalStateException
:
无法将类型“java.lang.long”的值转换为所需类型“com.fiberg.test.springboot.object.hut”:找不到匹配的编辑器或转换策略
可能的解决办法
使用一个简单的@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);
}
}
// ...
public class SomeBeanTest {
@Autowired private MyBeanSupplier supplier;
// ...
public void setUp() throws Exception {
someBean = supplier.getMyBean("2");
}
}
someBean = ctx.getBean(SomeBean.class, "2");
经过一些实验,这似乎是使用CDI bean时的一个问题,而与我最初假设的PrimeFaces无关。 =============================================================================== 我对JSF和PrimeFaces还很陌生,因此任何指导都将非常感谢。我已经搜索了其他的帖子,并阅读了许多类似的,但没有找到解决方法。 我正试
我正试图用BlueJ完成一项为uni完成的任务,但我在第一个障碍上遇到了障碍。 在赋值中,我们得到了一个类,以及该类的构造函数、方法和参数的名称。我们不允许更改这些,因为赋值部分地由测试单元标记(或类似的东西)。 该类的一个构造函数如下所示 我已经(部分)完成了 我不明白的是为什么-为什么他们使用作为构造函数的参数?这样做有什么好处? (我想这样做肯定有好处(如果没有,功能就不会存在),但我不明白
问题内容: 从风格上讲,我更喜欢这种结构: 为此结构: 从功能上讲,以这种方式构造代码是否有任何弊端?将原型方法添加到构造函数内部的原型对象中(即,在构造函数的表达式语句关闭之前)会导致意外的作用域问题吗? 在成功使用之前,我已经使用了第一种结构,但是我想确保自己不会因为调试错误而使自己陷入头痛,也不会引起开发人员的同情和痛苦。 问题答案: 从功能上讲,以这种方式构造代码是否有任何弊端?将原型方法
问题内容: 从文档中学习React 并遇到以下示例: 根据Mozilla的说法,super允许您在构造函数中使用。是否有其他原因可以单独使用(我知道也可以访问父类的方法),但是使用React时,是否还有其他仅通过自身调用的用例? 问题答案: 仅在具有构造函数的React组件内部被调用。例如,以下代码不需要超级: 但是,如果我们有一个构造函数,那么它是强制性的: 之所以不能被允许之前的原因是因为未调
问题内容: Java为什么不支持C ++中的复制构造函数? 问题答案: Java。只是没有像在C ++中那样隐式地调用它们,我怀疑这是您的真正问题。 首先,复制构造函数无非是: 现在,C ++将使用以下语句隐式调用复制构造函数: 在这种情况下,克隆/复制在Java中根本没有意义,因为所有b1和b2都是引用,而不是像C 中那样的值对象。在C 中,该语句复制对象的状态。在Java中,它只是复制 引用
问题内容: 有谁知道为什么可以使用或而不是非静态方法在构造函数的第一行中引用方法? 考虑以下工作: 以及以下非工作示例: 问题答案: 非静态方法是实例方法。这只能在现有实例中访问,并且在构造函数中时实例尚不存在(它仍在构建中)。 为什么会这样呢?因为实例方法可以访问实例(非静态)字段,该字段在不同实例中可以具有不同的值,所以在现有的已完成实例之外的其他地方调用这种方法没有任何意义。