没有自动装配的Spring组件扫描?

时间:2013-04-20 02:44:27

标签: java spring spring-mvc autowired

使用组件扫描而不使用弹簧自动装配是否有意义?

我喜欢在控制器的MVC环境中进行组件扫描的想法,我甚至想避免在xml上声明所有DAO,Services ....

但是,我不是自动装配的忠实粉丝,那么,是否仍然可以使用xml配置文件手动注入所需的bean,还是仅仅是无意义的?

更新:使用@Autowired而不是通过XML进行显式声明会有什么好处(请不要提供“少xml配置”作为优势)

3 个答案:

答案 0 :(得分:2)

我会

  • @Component添加到实现类中,以便为每个类创建一个bean
  • 不将@Autowired / @Resource与其他类中与这些实现相对应的成员声明关联起来,以便Spring不能autowire
  • 使用<bean>节点和<property>元素在XML中定义需要这些组件bean的bean,通过setter或<constructor-arg>注入它们以通过构造函数注入它们。

示例:

接口:

package com.krovi.compscan;

public interface MyInterface
{
    void method();
}

实现声明为Spring DI框架的组件,为此创建一个bean:

package com.krovi.compscan;

import org.springframework.stereotype.Component;

@Component
public class MyImpl implements MyInterface
{
    public void method()
    {
        System.out.println("Method definition in the implementation");
    }
}

一个典型的客户端,它将使用基于组件的bean,但通过构造函数通过构造函数显式注入。

package com.krovi.compscan;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyClient
{
    private MyInterface myInterface;

    public MyClient(MyInterface i)
    {
        this.myInterface = i;
    }

    public void clientMethod()
    {
        myInterface.method();
    }

    // Main method to test.    
    public static void main(
        String[] args)
    {
        ClassPathXmlApplicationContext context =
            new ClassPathXmlApplicationContext("classpath:META-INF/compscan.xml");
        MyClient client =
            context.getBean(MyClient.class);
        client.clientMethod();
    }
}

另一个典型的客户端将使用基于组件的bean,但使用setter通过配置文件显式注入:

package com.krovi.compscan;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyAnotherClient
{
    private MyInterface impl;

    protected MyAnotherClient()
    {

    }

    public MyInterface getImpl()
    {
        return impl;
    }

    public void setImpl(
        MyInterface impl)
    {
        this.impl = impl;
    }

    public void clientMethod()
    {
        impl.method();
    }

    public static void main(
        String[] args)
    {
        ClassPathXmlApplicationContext context =
            new ClassPathXmlApplicationContext("classpath:META-INF/compscan.xml");
        MyAnotherClient client =
            context.getBean(MyAnotherClient.class);
        client.clientMethod();
    }
}

Bean配置文件:

<?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-3.0.xsd">

    <!-- Component scan to create beans for @Component classes -->
    <context:component-scan base-package="com.krovi.compscan" />

    <!-- Explicit bean declaration for clients to get the 
         @Component classes injected 
    -->
    <bean id="myClient" class="com.krovi.compscan.MyClient">
        <constructor-arg ref="myImpl" />
    </bean>
    <bean id="anotherClient" class="com.krovi.compscan.MyAnotherClient">
        <property name="impl" ref="myImpl" />
    </bean>
</beans>

答案 1 :(得分:1)

Xml声明优先于注释,因此您不能同时使用它们。

但是,如果您不想使用DI,为什么还要通过注释声明组件?这毫无意义。

答案 2 :(得分:0)

它是可修复的,取决于您更喜欢声明组件“Spring beans”:

  1. 使用component-scan

  2. 使用

  3. 以XML格式编写

    还可以由您来定义组件之间的关系:

    1. 使用@Autowired

    2. 使用或在xml中

    3. 2动作不同,就像在另一个bean的属性中初始化bean和设置bean的引用一样,使用“component-scan”和“@Autowired”的唯一一点是@Autowired正在使用类型和“组件-scan“不强制生成bean的id或名称,所以最好同时使用它们,但如果你想在不使用自动装配的情况下使用扫描,你必须注意不要使用具有相同类名的2个组件,也要关心写作参考名称的任何拼写错误。