【问题标题】:How to AutoWire an object without Spring XML context file?如何在没有 Spring XML 上下文文件的情况下自动连接对象?
【发布时间】:2012-09-28 17:16:48
【问题描述】:

我有一个带有Component 注释的接口和一些实现它的类,如下所示:

@Component
public interface A {
}

public class B implements A {
}
public class C implements A {
}

另外,我有一个带有 Autowired 变量的类,如下所示:

public class Collector {
    @Autowired
    private Collection<A> objects;

    public Collection<A> getObjects() {
        return objects;
    }
}

我的上下文文件包含以下定义:

<context:component-scan base-package="org.iust.ce.me"></context:component-scan>

<bean id="objectCollector" class="org.iust.ce.me.Collector" autowire="byType"/>

<bean id="b" class="org.iust.ce.me.B"></bean>
<bean id="c" class="org.iust.ce.me.C"></bean>

在主类中,我有一些代码如下:

ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
B b = (B) context.getBean("b");
C c = (C) context.getBean("c");
Collector objectCollector = (Collector) context.getBean("objectCollector");

for (A object : objectCollector.getObjects()) {
    System.out.println(object);
}

输出:

org.iust.ce.me.B@1142196
org.iust.ce.me.C@a9255c

这些代码运行良好,但由于某些原因我不愿意使用 xml 上下文文件。除此之外,我更喜欢使用new 运算符而不是使用getBean() 方法来创建对象。尽管如此,由于AutoWiring 在编程中确实是个好主意,我不想失去它。

现在我有两个问题!!

  1. 如何在不使用 xml 上下文文件的情况下实现 A 接口的 AutoWire 类?
    有可能吗?

  2. 当我将 bean 的 scopesinglton 更改为 prototype如下:

    &lt;bean id="b" class="org.iust.ce.me.B" scope="prototype"&gt;&lt;/bean&gt;

    并实例化它的几个bean,只有在创建context 期间实例化的bean 是injectedAutoWired 变量。为什么?

任何帮助将不胜感激。

【问题讨论】:

    标签: java spring jakarta-ee ioc-container autowired


    【解决方案1】:

    不确定您使用的 Spring 版本。但目前您可以使用@Configuration 替换.xml。看看@Configuration

    以下是文档中的代码

    @Configuration
    public class ServiceConfig {
        private @Autowired RepositoryConfig repositoryConfig;
        public @Bean TransferService transferService() {
            return new TransferServiceImpl(repositoryConfig.accountRepository());
        }
    }
    
    @Configuration
    public interface RepositoryConfig {
        @Bean AccountRepository accountRepository();
    }
    
    @Configuration
    public class DefaultRepositoryConfig implements RepositoryConfig {
        public @Bean AccountRepository accountRepository() {
            return new JdbcAccountRepository(...);
        }
    }
    
    @Configuration
    @Import({ServiceConfig.class, DefaultRepositoryConfig.class}) // import the concrete config!
    public class SystemTestConfig {
        public @Bean DataSource dataSource() { /* return DataSource */ }
    }
    public static void main(String[] args) {
        ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class);
        TransferService transferService = ctx.getBean(TransferService.class);
        transferService.transfer(100.00, "A123", "C456");
    }
    

    【讨论】:

    • 太棒了!希望我能为此付出超过+1。感谢您找到并发布代码 - 永远不会在文档中如此深入......与 Neo4j 一起工作(来自this)。再次感谢您!
    【解决方案2】:

    如果要管理的类已经正确注释,Spring 可以扫描应用程序的文件以获取所需的信息,而无需任何 xml 或 java 配置文件。

    AnnotationConfigApplicationContext  context = new AnnotationConfigApplicationContext();
    context.scan("com.something.something.etc");
    context.refresh();
    ...context.getBean("name_of_bean");
    

    注意AnnotationConfigApplicationContext 是在没有任何参数的情况下实例化的。 context.scan("..."); 接受一个字符串,告诉 Spring 去哪里看。即包

    com.something.something.etc.one
    com.comething.something.etc.two
    将被扫描,这些包中带有@Component@Autowired等注释的类将在需要时被实例化和注入。

    这种方法似乎没有很好的文档记录。

    【讨论】:

    • 尽可能提供更多的cmets。
    【解决方案3】:

    1- 您需要编写另一个类来执行该操作。将@Component 写入B 和C 类。

    public static void main(){
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");  
        InitClass initClass = (InitClass) context.getBean("initClass");  
    }
    
    
    public class InitClass{  
       @Autowired 
       public B b;
    
       @Autowired 
       public C c;
    }
    

    有了这个,你将获得 B 和 C,而无需使用 xml。

    2- http://static.springsource.org/spring/docs/3.0.0.M3/reference/html/ch04s04.html Bean 作用域在此处详述。如果你总是想要一个新对象,你应该使用原型,但创建一个新对象将在不同的类中完成。在同一个类中,您应该添加一个新的引用。

    喜欢

    public class InitClass{
        @Autowired 
        public A a1;
    
        @Autowired 
        public A a2;
    
    }
    

    【讨论】:

    • +0.5!很好的答案,但我仍然必须使用 XML 上下文文件。此外,在您的代码中,实现A 接口的类手动添加到InitClass。在我的项目中,有几个类实现了A 接口,我不想手动处理它们。
    • 您必须在启动时初始化 xml 以使用 Spring 您要从 main 方法访问的第一个对象应该使用 context.getBean 获取,如果存在@Autowired,其他对象将被注入。对于动态创建新对象,你必须使用 context.getBean,我认为在 spring 中没有其他方法。
    • 我认为使用 new 运算符创建 Spring bean 是可能的,但我不知道如何完成。扫一眼this question
    • 那个问题也有答案,你必须使用 AOP 并用 maven 或 ant 编译你的项目。我之前没有做过,也许你应该看看提供的链接static.springsource.org/spring/docs/current/…eclipse.org/aspectj/doc/released/devguide/ltw.html
    猜你喜欢
    • 1970-01-01
    • 2014-12-05
    • 2011-09-13
    • 1970-01-01
    • 1970-01-01
    • 2020-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多