Spring DI:从XML到Annotations

时间:2016-01-27 16:08:14

标签: java spring dependency-injection annotations

仅出于教育原因,我正在尝试探索使用注释或XML配置与DI的区别。

为了做到这一点,我有一个Messager应用程序的例子,它可以使用不同的实现来做不同类型的工作(发送电子邮件,发送短信)。

使用测试类我可以从工厂获取bean,如果需要,可以注入不同的实现。

它的外观如下:

IMessageService.java

    public interface IMessageService {

       public void sendMessage(String message, String recipient);

    }

EmailMessageServiceImpl.java

public class EmailMessageServiceImpl implements IMessageService {

    @Override
    public void sendMessage(String message, String recipient) {
        //Validations email, etc.
        System.out.println(String.format("EMAIL Message: %s. Recipient: %s", message, recipient));
    }

}

SMSMessageServiceImpl.java

public class SMSMessageServiceImpl implements IMessageService {

    @Override
    public void sendMessage(String message, String recipient) {
        //Phone validations
        System.out.println(String.format("SMS message: %s. Sent to: %s", message, recipient));
    }

}

App.java

    public class App {

        private IMessageService messageService;

        public void processMessages(String message, String recipient) {

            messageService.sendMessage(message, recipient);

        }

        public void setMessageService(IMessageService messageService) {
            this.messageService = messageService;
        }

}

的applicationContext.xml

    <!--    Declaring the App and injecting two different implementations of IMessageService-->
<bean id="appEmail" class="org.invenio.tic.holamundospring.App">
    <property name="messageService" ref="emailImpl"/>
</bean>

<bean id="appSMS" class="org.invenio.tic.holamundospring.App">
    <property name="messageService" ref="smsImpl"/>
</bean>


<!--    Declaring the beans with the implementations-->
<bean id="emailImpl" class="org.invenio.tic.holamundospring.service.EmailMessageServiceImpl"/>

<bean id="smsImpl" class="org.invenio.tic.holamundospring.service.SMSMessageServiceImpl"/>

最后是测试课 Main.java

    public class Main {

        public static void main(String[] args) {

        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

        App app = (App) context.getBean("appEmail");
        app.processMessages("Hi, this is an email", "info@invenio.org");

        app = (App) context.getBean("appSMS");
        app.processMessages("This is an SMS", "88100452");

    }

}

打印:

    EMAIL Message: Hi, this is an email. Recipient: info@invenio.org
    SMS message: This is an SMS. Sent to: 88100452

当我尝试使用Annotations,使用Spring的自动装配和自动发现功能时,我失去了使用不同实现获取应用程序的能力,因为Annotation @Autowired让我选择我想要的实现,但它将被硬编码到App.java类。

App.java

    @Component
    public class App {

    @Autowired
    @Qualifier("emailServiceImpl")
    private IMessageService messageService;

    public void processMessages(String message, String recipient) {

        messageService.sendMessage(message, recipient);

    }

    public void setMessageService(IMessageService messageService) {
        this.messageService = messageService;
    }

}

有没有解决这个问题的方法?比如在参数中传递限定符名称,或者让我在运行时更改MessageService的实现?

或者这是使用Annotations的缺点之一吗?

由于 -Alejandro。

2 个答案:

答案 0 :(得分:0)

尝试将@Qualifier("emailServiceImpl")更改为@Qualifier("emailImpl"),就像在applicationContext.xml中定义一样。

答案 1 :(得分:0)

你可以使用这样的app构造函数来完成它:

配置类:

@Configuration
@ComponentScan("com.anno") //your package goes here
public class Config {

    @Bean(name = "appEmail")

    public App appEmail(@Qualifier("EmailMessageServiceImpl") IMessageService messageService) {
        return new App(messageService);
    }

    @Bean(name = "appSMS")
    public App appSms(@Qualifier("SMSMessageServiceImpl") IMessageService messageService) {
        return new App(messageService);
    }
}

App类:

@Component

    public class App {

        private IMessageService messageService;

        public App() {
        }
        public App(IMessageService messageService) {
            this.messageService = messageService;
        }
        public void processMessages(String message, String recipient) {

            messageService.sendMessage(message, recipient);

        }

        public void setMessageService(IMessageService messageService) {
            this.messageService = messageService;
        }

    }

服务类:

@Service("SMSMessageServiceImpl")
public class SMSMessageServiceImpl implements IMessageService {

    public void sendMessage(String message, String recipient) {
        // Phone validations
        System.out.println(String.format("SMS message: %s. Sent to: %s", message, recipient));
    }

}

@Service("EmailMessageServiceImpl")
public class EmailMessageServiceImpl implements IMessageService {

    public void sendMessage(String message, String recipient) {
        // Validations email, etc.
        System.out.println(String.format("EMAIL Message: %s. Recipient: %s", message, recipient));
    }

}

主要类别:

public class Main {

    public static void main(String[] args) {

        ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);

        App app = (App) context.getBean("appEmail");
        app.processMessages("Hi, this is an email", "info@invenio.org");

        app = (App) context.getBean("appSMS");
        app.processMessages("This is an SMS", "88100452");

}

}

希望这可以提供帮助。