我们以一个简单的图书管理系统作为例子,给大家分析java代码的Spring配置。首行看一下代码结构,该系统有两个接口,分别是查询书籍接口和卖书规则接口,其中查询书籍接口分别有按出版社查询和按书本类别查询两个实现类,卖书规则接口分别有满额减价优惠和满额打折优惠。然后AppConfigutration就是我们的配置类,TaobaoSell就是我们的装配类啦!
看看各个类
首先是实体类,还不知道lombok的同学们抓紧学习一下啦,超级方便的。
@Data
@NoArgsConstructor
@AllArgsConstructor
public abstract class Book {
private String name;
private String publisher;
private String type;
private Integer price;
}
然后就是根据出版社找书(两种相似),为了方便大家理解,所以没有连接数据库,大家见谅(BookFinder接口就是一个抽象方法,就不再上传啦,后备源码)。别外,还不会JDK8加的lambda表达式的同学也可以了解一下的哟。
public class FindByPublisher implements BookFinder {
private List<Book> bookList = null;
public FindByPublisher() {
bookList = new ArrayList<>();
bookList.add(new Book("安徒生童话", "中国人民教育出版社", "儿童书籍", 38));
bookList.add(new Book("一千零一夜", "清华大学出版社", "儿童书籍", 26));
bookList.add(new Book("安徒生童话", "山西少年宫出版社", "儿童书籍", 64));
bookList.add(new Book("操作系统", "清华大学出版社", "程序员书籍", 88));
bookList.add(new Book("java程序基础", "天津科教出版社", "程序员书籍", 36));
bookList.add(new Book("数据库原理及理论", "高等教育出版社", "程序员书籍", 78));
bookList.add(new Book("中国近现代史纲要", "清华大学出版社", "政治书籍", 60));
bookList.add(new Book("思想道德修养与法律基础", "高等教育出版社", "政治书籍", 98));
}
@Override
public List<Book> findBooks(String publisher) {
return bookList.stream().
filter(book -> book.getPublisher().equals(publisher))
.collect(Collectors.toList());
}
}
接着我们将打折的方式也加上。
//优惠,满70减10块
public class SellingRuleReduce implements SellingRule {
@Override
public int reducePrice(Book book) {
if (book.getPrice() > 70)
return book.getPrice() - 10;
return book.getPrice();
}
}
然后就是装配类。将两种查询书籍方式和两种卖书折扣规则用构造方法置入装配类TaobaoSell。
public class TaobaoSell {
private BookFinder bookFinder;
private SellingRule sellingRule;
public TaobaoSell(BookFinder bookFinder, SellingRule sellingRule) {
this.bookFinder = bookFinder;
this.sellingRule = sellingRule;
}
List<Book> findBookByPublisher(String publisher){
return bookFinder.findBooks(publisher);
}
List<Book> findBookByType(String type){
return bookFinder.findBooks(type);
}
int sellingRuleDiscount(Book book){
return sellingRule.reducePrice(book);
}
int sellingRuleReduce(Book book){
return sellingRule.reducePrice(book);
}
}
到了我们最重要的配置类。@Configuration表示该类是配置类(一定不要忘记),@Bean表示将该类交由Spring容器来管理,@Bean后面的括号表示该类放入容器的名称,而下面的taobaoSell()方法中的BookFinder会出现找到两个实现类的情况,所以用@Qualifier注解区分,如果@Bean不改名,该注解括号里的内容就是实体类首字母小写,像@Qualifier("sellingRuleReduce"),如果@Bean改名,该注解括号里就是改之后的名字@Qualifier("byPublisher")。还有别的方式区别,比如@Primary大家私下了解。
@Configuration
public class AppConfiguration {
@Bean("byPublisher")
public BookFinder findByPublisher(){
return new FindByPublisher();
}
@Bean
public BookFinder findByType(){
return new FindByType();
}
@Bean
public SellingRule sellingRuleDiscount(){
return new SellingRuleDiscount();
}
@Bean
public SellingRule sellingRuleReduce(){
return new SellingRuleReduce();
}
@Bean
public TaobaoSell taobaoSell(@Qualifier("byPublisher") BookFinder bookFinder, @Qualifier("sellingRuleReduce") SellingRule sellingRule){
return new TaobaoSell(bookFinder,sellingRule);
}
}
最后就是要测试我们的结果啦。我们可以用Application创建对象container,这时我们就再也不用new对象啦,想要任何实体体创建对象只要用container调用getBean(Class<T> requiredType)方法就行啦。我们的sell对象并没有通过new得到,但是此时已经可以调用需要的方法,只要传入合适的参数即可,Spring的功能就已经完全实现了。
@SpringBootApplication
public class InjectionJavacodeApplication {
public static void main(String[] args) {
ApplicationContext container = SpringApplication.run(InjectionJavacodeApplication.class, args);
TaobaoSell sell = container.getBean(TaobaoSell.class);
List<Book> bookList1 = sell.findBookByPublisher("清华大学出版社");
for (Book book : bookList1) {
System.out.println(book);
}
Book book = bookList1.get(1);
int priceBefore = book.getPrice();
int priceAfter = sell.sellingRuleDiscount(book);
System.out.println(book.getName() + ",该书打折前价格为:" + priceBefore);
System.out.println(book.getName() + ",该书打折后价格为:" + priceAfter);
}
}
大家如果有源码需要,可以参考https://github.com/bluetie915/CSDN/tree/master/injection-javacode