AnnotationConfigApplicationContext和父上下文

我正在尝试使用AnnotationConfigApplicationContext定义上下文层次结构。

问题是在beanRefContext.xml定义模块上下文并使用另一个上下文(基于XML / Annotated)设置’parent’属性。

例:

模块A中的beanRefContext.xml

 
     
         
             类路径:DB-context.xml中
         
     
 

DB-的context.xml

 

 
 
         
         
         
             
                  com.example.model 
             
         
         
         
         
 

模块B中的beanRefContext.xml

 
     
         
             
                  com.example.dao 
             
         
 

FooHibernateDao

 class FooHibernateDao实现FooDao {
     @Autowired
     @Qualifier( “SessionFactory的”)
     private SessionFactory sessionsFactory;

     // CRUD方法
 }

模块B应用程序上下文无法找到模块A应用程序上下文中定义的bean。
通过查看AnnotationConfigApplicationContext的代码,似乎扫描过程不使用父作为解析bean的引用。

有什么我做错了或者我的注释配置是不可能尝试创建层次结构?

问题源于AnnotationConfigApplicationContext的构造函数执行扫描的事实。 因此,父级未设置在此阶段,仅在扫描完成后设置,因为父级由属性设置 – 因此它找不到您的bean的原因。

默认的AnnotationConfigApplicationContext bean没有带父工厂的构造函数 – 不知道为什么。

您可以使用常规的基于xml的应用程序上下文并在其中配置注释扫描,也可以创建将创建注释应用程序上下文的自定义fatory bean。 这将指定父引用,然后执行扫描。

看看来源……

工厂看起来像这样:

 public class AnnotationContextFactory implements FactoryBean { private String[] packages; private ApplicationContext parent; @Override public ApplicationContext getObject() throws Exception { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.setParent(parent); context.scan(packages); context.refresh(); return context; } @Override public Class getObjectType() { return ApplicationContext.class; } @Override public boolean isSingleton() { return true; } public void setPackages(String... args) { this.packages = args; } public void setParent(ApplicationContext parent) { this.parent = parent; } } 

你的bean定义:

     za.co.test2    

不要将XML用于子上下文。 使用ctx.setParent然后使用ctx.register。 喜欢这个:

 public class ParentForAnnotationContextExample { public static void main(String[] args) { ApplicationContext parentContext = new AnnotationConfigApplicationContext(ParentContext.class); AnnotationConfigApplicationContext childContext = new AnnotationConfigApplicationContext(); childContext.setParent(parentContext); childContext.register(ChildContext.class); //don't add in the constructor, otherwise the @Inject won't work childContext.refresh(); System.out.println(childContext.getBean(ParentBean.class)); System.out.println(childContext.getBean(ChildBean.class)); childContext.close(); } @Configuration public static class ParentContext { @Bean ParentBean someParentBean() { return new ParentBean(); } } @Configuration public static class ChildContext { @Bean ChildBean someChildBean() { return new ChildBean(); } } public static class ParentBean {} public static class ChildBean { //this @Inject won't work if you use ChildContext.class in the child AnnotationConfigApplicationContext constructor @Inject private ParentBean injectedFromParentCtx; } } 

我遇到了同样的问题,

如果要从java实例化AnnotationConfigApplicationContext,另一种可能性是扩展AnnotationConfigApplicationContext并仅添加所需的构造函数或以编程方式构建上下文。

我做的是以下内容:

 BeanFactoryLocator locator = ContextSingletonBeanFactoryLocator.getInstance("classpath:beanRefContext.xml"); BeanFactoryReference parentContextRef = locator.useBeanFactory("ear.context"); ApplicationContext parentContext = (ApplicationContext) parentContextRef.getFactory(); childContext.setParent(parentContext); 

猜猜看,它有效 🙂

PS:如果有人知道如何用@Configuration类替换classpath:beanRefContext.xml,请让我们都知道。