在Spring 3.1中,有一种方法可以自动填充类型化的List,这在您想在代码中稍微进行去耦和清理时非常方便。
为了向您展示它是如何工作的,我将实现一个简单的责任链,该责任链将为通过的用户打印一些问候。
让我们从我们拥有的(唯一的)域类(用户)开始:
package com.marco.springchain;
public class User {private final String name;private final char gender;public User(String name, char gender) {super();this.name = name;this.gender = gender;}public String getName() {return name;}public char getGender() {return gender;}
}
然后,我们创建一个接口,该接口定义要在链中使用的命令对象的类型:
package com.marco.springchain;
public interface Printer {void print(User user);
}
这是Printer实现的通用类(模板)。
org.springframework.core.Ordered
用于告诉AnnotationAwareOrderComparator我们希望如何对List进行排序。
如果不需要您的链来具有执行顺序,则无需实现Ordered接口并重写getOrder方法。
还要注意,这个抽象类返回Ordered.LOWEST_PRECEDENCE
,这是因为我希望一些打印机命令仅在链的末尾运行,并且我不在乎它们的执行顺序(我保证,以后一切都会更清楚!)。
GenericPrinter
这是我们的第一个真正的打印机命令。 我希望它在链中具有绝对优先级,因此顺序为HIGHEST_PRECEDENCE
。
package com.marco.springchain;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
@Component
public class HelloPrinter extends GenericPrinter {private static final String GREETING = 'Hello';@Overrideprotected String getGreeting() {return GREETING;}@Overridepublic int getOrder() {return Ordered.HIGHEST_PRECEDENCE;}
}
WelcomePrinter
将作为第一个命令执行( 在高优先级命令之后 )。
package com.marco.springchain;
import org.springframework.stereotype.Component;
@Component
public class WelcomePrinter extends GenericPrinter {private static final String GREETING = 'Welcome to the autowired chain';@Overrideprotected String getGreeting() {return GREETING;}@Overridepublic int getOrder() {return 1;}
}
GoodbyePrinter
将作为第二个命令执行
package com.marco.springchain;
import org.springframework.stereotype.Component;
@Component
public class GoodbyePrinter extends GenericPrinter {private static final String GREETING = 'Goodbye';@Overrideprotected String getGreeting() {return GREETING;}@Overridepublic int getOrder() {return 2;}
}
这两个命令需要在其他命令之后执行,但是我不在乎它们的特定顺序,因此我不会覆盖getOrder方法,而让GenericPrinter Ordered.LOWEST_PRECEDENCE
为这两个命令返回Ordered.LOWEST_PRECEDENCE
。
package com.marco.springchain;
import org.springframework.stereotype.Component;
@Component
public class CleaningMemoryPrinter extends GenericPrinter {private static final String GREETING = 'Cleaning memory after';@Overrideprotected String getGreeting() {return GREETING;}
}
package com.marco.springchain;
import org.springframework.stereotype.Component;
@Component
public class CleaningSpacePrinter extends GenericPrinter {private static final String GREETING = 'Cleaning space after';@Overrideprotected String getGreeting() {return GREETING;}
}
这是链上下文。
Spring将扫描(请参阅spring-config.xml)配置文件中指定的包,它将看到类型化的( List<Printer>
)列表,并且它将使用实现该类型的任何@Component
的实例填充该列表。打印机。
为了对List进行排序,我们使用AnnotationAwareOrderComparator.INSTANCE
,它使用getOrder方法对List进行重新排序( 值最低的对象具有最高优先级(有点类似于Servlet“启动时加载”值 ) )。
package com.marco.springchain;
import java.util.Collections;
import java.util.List;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.stereotype.Component;
@Component
public class PrinterChain {@Autowiredprivate List<Printer> printers;@PostConstructpublic void init() {Collections.sort(printers, AnnotationAwareOrderComparator.INSTANCE);}public void introduceUser(User user) {for (Printer printer : printers) {printer.print(user);}}
}
src / main / resources中的spring-config.xml。
<?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:aop='http://www.springframework.org/schema/aop'xmlns:tx='http://www.springframework.org/schema/tx'xmlns:context='http://www.springframework.org/schema/context'xmlns:util='http://www.springframework.org/schema/util'xsi:schemaLocation='http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsdhttp://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd' default-lazy-init='true'><context:component-scan base-package='com.marco.springchain'/>
</beans>
最后,一个主类来测试我们的链。
package com.marco.springchain;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainTest {public static void main(String[] args) {ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext('spring-config.xml');PrinterChain printerChain = (PrinterChain) context.getBean('printerChain');printerChain.introduceUser(new User('Marco Castigliego', 'M'));printerChain.introduceUser(new User('Julie Marot', 'F'));}
}
输出:
Hello Mr Marco Castigliego
Welcome to the autowired chain Mr Marco Castigliego
Goodbye Mr Marco Castigliego
Cleaning space after Mr Marco Castigliego
Cleaning memory after Mr Marco Castigliego
Hello Mrs Julie Marot
Welcome to the autowired chain Mrs Julie Marot
Goodbye Mrs Julie Marot
Cleaning space after Mrs Julie Marot
Cleaning memory after Mrs Julie Marot
希望您喜欢这个例子。
参考: 使用来自我们的JCG合作伙伴 Marco Castigliego的Spring @Autowired List的责任链,位于“ 删除重复和修复不良名称”博客中。
翻译自: https://www.javacodegeeks.com/2012/11/chain-of-responsibility-using-spring-autowired-list.html