Micronaut:从上下文中获取 bean 的问题
Micronaut: problem with getting bean from context
我有一个 class,其中包含注入和强制(最终)字段。对于常见的情况,我可以使用 MicronautBeanFactory.getBean(type) 或 BeanContext.getBean(type) 从上下文中获取 bean,但在这种情况下,我必须传递类型和参数。
我为此创建了简单的测试
@MicronautTest
public class ETLExecutorTest {
@Inject
private MicronautBeanFactory micronautBeanFactory;
@Test
void testGetBean() {
Object[] args = new Object[] {"name", "spec", 1L};
ObjectInstance instance = micronautBeanFactory.getBean(ObjectInstance.class, args);
}
}
对象(bean)代码
@Prototype
public class ObjectInstance {
@Inject
private ObjectStorage objectStorage;
private final String name;
private final String spec;
private final Long id;
public ObjectInstance(String name, String spec, Long id) {
this.name = name;
this.spec = spec;
this.id = id;
}
}
当我 运行 收到异常时
io.micronaut.context.exceptions.DependencyInjectionException: Failed to inject value for parameter [name] of class: com.ObjectInstance
Message: Multiple possible bean candidates found: [java.lang.String, java.lang.String, java.lang.String]
Path Taken: new ObjectInstance([String name],String specName,Long accountId)
at io.micronaut.context.AbstractBeanDefinition.getBeanForConstructorArgument(AbstractBeanDefinition.java:1016)
at com.$TableInstanceDefinition.build(Unknown Source)
at io.micronaut.context.DefaultBeanContext.doCreateBean(DefaultBeanContext.java:1598)
at io.micronaut.context.DefaultBeanContext.getScopedBeanForDefinition(DefaultBeanContext.java:2076)
at io.micronaut.context.DefaultBeanContext.getBeanForDefinition(DefaultBeanContext.java:1991)
at io.micronaut.context.DefaultBeanContext.getBeanInternal(DefaultBeanContext.java:1963)
at io.micronaut.context.DefaultBeanContext.getBean(DefaultBeanContext.java:610)
at io.micronaut.spring.context.factory.MicronautBeanFactory.getBean(MicronautBeanFactory.java:264)
Caused by: io.micronaut.context.exceptions.NonUniqueBeanException: Multiple possible bean candidates found: [java.lang.String, java.lang.String, java.lang.String]
at io.micronaut.context.DefaultBeanContext.findConcreteCandidate(DefaultBeanContext.java:1701)
at io.micronaut.context.DefaultApplicationContext.findConcreteCandidate(DefaultApplicationContext.java:395)
at io.micronaut.context.DefaultBeanContext.lastChanceResolve(DefaultBeanContext.java:2289)
at io.micronaut.context.DefaultBeanContext.findConcreteCandidateNoCache(DefaultBeanContext.java:2212)
at io.micronaut.context.DefaultBeanContext.lambda$findConcreteCandidate(DefaultBeanContext.java:2155)
at io.micronaut.core.util.clhm.ConcurrentLinkedHashMap.lambda$compute[=13=](ConcurrentLinkedHashMap.java:721)
at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660)
at io.micronaut.core.util.clhm.ConcurrentLinkedHashMap.compute(ConcurrentLinkedHashMap.java:733)
at io.micronaut.core.util.clhm.ConcurrentLinkedHashMap.computeIfAbsent(ConcurrentLinkedHashMap.java:710)
at io.micronaut.context.DefaultBeanContext.findConcreteCandidate(DefaultBeanContext.java:2154)
at io.micronaut.context.DefaultBeanContext.getBeanInternal(DefaultBeanContext.java:1943)
at io.micronaut.context.DefaultBeanContext.getBean(DefaultBeanContext.java:1082)
at io.micronaut.context.AbstractBeanDefinition.getBeanForConstructorArgument(AbstractBeanDefinition.java:1007)
我也尝试做另一个测试,但在这种情况下,我收到了没有注入字段的对象
@MicronautTest
public class ETLExecutorTest {
@Inject
private BeanContext beanContext;
@Test
void testGetBean() {
Object[] args = new Object[] {"name", "spec", 1L};
BeanDefinition<ObjectInstance> definition = beanContext.getBeanDefinition(ObjectInstance.class);
ObjectInstance instance = definition.getConstructor().invoke(args); // there are no injections here: ObjectStorage of instance = null.
}
}
你能告诉我,我做错了什么吗???
micronaut
试图通过 构造函数 创建 bean ObjectInstance
但找不到要注入的 String name
,看起来它只是一个ObjectInstance
的简单字段,在本例中,它按预期工作:
io.micronaut.context.exceptions.DependencyInjectionException: Failed to inject value for parameter [name]
如果你添加一个默认构造函数,那么ObjectInstance
将被创建,你可以通过beanContext.getBean(ObjectInstance.class)
:
获取bean
@Prototype
public class ObjectInstance {
@Inject
private ObjectStorage objectStorage;
private String name;
private String spec;
private Long id;
public ObjectInstance() {}
public ObjectInstance(String name, String spec, Long id) {
this.name = name;
this.spec = spec;
this.id = id;
}
}
另外注意MicronautBeanFactory implements ListableBeanFactory,这个是为了和Spring
整合
P.S。我建议您更改代码结构,POJO
不应包含 beans
我有一个 class,其中包含注入和强制(最终)字段。对于常见的情况,我可以使用 MicronautBeanFactory.getBean(type) 或 BeanContext.getBean(type) 从上下文中获取 bean,但在这种情况下,我必须传递类型和参数。
我为此创建了简单的测试
@MicronautTest
public class ETLExecutorTest {
@Inject
private MicronautBeanFactory micronautBeanFactory;
@Test
void testGetBean() {
Object[] args = new Object[] {"name", "spec", 1L};
ObjectInstance instance = micronautBeanFactory.getBean(ObjectInstance.class, args);
}
}
对象(bean)代码
@Prototype
public class ObjectInstance {
@Inject
private ObjectStorage objectStorage;
private final String name;
private final String spec;
private final Long id;
public ObjectInstance(String name, String spec, Long id) {
this.name = name;
this.spec = spec;
this.id = id;
}
}
当我 运行 收到异常时
io.micronaut.context.exceptions.DependencyInjectionException: Failed to inject value for parameter [name] of class: com.ObjectInstance Message: Multiple possible bean candidates found: [java.lang.String, java.lang.String, java.lang.String] Path Taken: new ObjectInstance([String name],String specName,Long accountId) at io.micronaut.context.AbstractBeanDefinition.getBeanForConstructorArgument(AbstractBeanDefinition.java:1016) at com.$TableInstanceDefinition.build(Unknown Source) at io.micronaut.context.DefaultBeanContext.doCreateBean(DefaultBeanContext.java:1598) at io.micronaut.context.DefaultBeanContext.getScopedBeanForDefinition(DefaultBeanContext.java:2076) at io.micronaut.context.DefaultBeanContext.getBeanForDefinition(DefaultBeanContext.java:1991) at io.micronaut.context.DefaultBeanContext.getBeanInternal(DefaultBeanContext.java:1963) at io.micronaut.context.DefaultBeanContext.getBean(DefaultBeanContext.java:610) at io.micronaut.spring.context.factory.MicronautBeanFactory.getBean(MicronautBeanFactory.java:264) Caused by: io.micronaut.context.exceptions.NonUniqueBeanException: Multiple possible bean candidates found: [java.lang.String, java.lang.String, java.lang.String] at io.micronaut.context.DefaultBeanContext.findConcreteCandidate(DefaultBeanContext.java:1701) at io.micronaut.context.DefaultApplicationContext.findConcreteCandidate(DefaultApplicationContext.java:395) at io.micronaut.context.DefaultBeanContext.lastChanceResolve(DefaultBeanContext.java:2289) at io.micronaut.context.DefaultBeanContext.findConcreteCandidateNoCache(DefaultBeanContext.java:2212) at io.micronaut.context.DefaultBeanContext.lambda$findConcreteCandidate(DefaultBeanContext.java:2155) at io.micronaut.core.util.clhm.ConcurrentLinkedHashMap.lambda$compute[=13=](ConcurrentLinkedHashMap.java:721) at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660) at io.micronaut.core.util.clhm.ConcurrentLinkedHashMap.compute(ConcurrentLinkedHashMap.java:733) at io.micronaut.core.util.clhm.ConcurrentLinkedHashMap.computeIfAbsent(ConcurrentLinkedHashMap.java:710) at io.micronaut.context.DefaultBeanContext.findConcreteCandidate(DefaultBeanContext.java:2154) at io.micronaut.context.DefaultBeanContext.getBeanInternal(DefaultBeanContext.java:1943) at io.micronaut.context.DefaultBeanContext.getBean(DefaultBeanContext.java:1082) at io.micronaut.context.AbstractBeanDefinition.getBeanForConstructorArgument(AbstractBeanDefinition.java:1007)
我也尝试做另一个测试,但在这种情况下,我收到了没有注入字段的对象
@MicronautTest
public class ETLExecutorTest {
@Inject
private BeanContext beanContext;
@Test
void testGetBean() {
Object[] args = new Object[] {"name", "spec", 1L};
BeanDefinition<ObjectInstance> definition = beanContext.getBeanDefinition(ObjectInstance.class);
ObjectInstance instance = definition.getConstructor().invoke(args); // there are no injections here: ObjectStorage of instance = null.
}
}
你能告诉我,我做错了什么吗???
micronaut
试图通过 构造函数 创建 bean ObjectInstance
但找不到要注入的 String name
,看起来它只是一个ObjectInstance
的简单字段,在本例中,它按预期工作:
io.micronaut.context.exceptions.DependencyInjectionException: Failed to inject value for parameter [name]
如果你添加一个默认构造函数,那么ObjectInstance
将被创建,你可以通过beanContext.getBean(ObjectInstance.class)
:
@Prototype
public class ObjectInstance {
@Inject
private ObjectStorage objectStorage;
private String name;
private String spec;
private Long id;
public ObjectInstance() {}
public ObjectInstance(String name, String spec, Long id) {
this.name = name;
this.spec = spec;
this.id = id;
}
}
另外注意MicronautBeanFactory implements ListableBeanFactory,这个是为了和Spring
整合
P.S。我建议您更改代码结构,POJO
不应包含 beans