什么?你要问我applicationContext.xml这个配置文件该怎么配置?你可知道,XML配置文件的方式是在Spring1.0的时代使用的,现在都到了Spring5,你还在用,不觉得out吗!什么,你说问我的是properties配置文件(SpringBoot采用properties配置的方式和yaml的方式),好吧,这个不过时,不过这是SpringBoot的配置,这里我们不说!
Spring的配置随着Spring的版本的升级大概经历了3个阶段,从最初的XML配置方式到使用注解配置,到现在的使用Java类来进行配置。
- 在Spring 1版本的时候,只有xml配置,所有的Bean都需要使用xml来进行配置,导致项目中出现大量的配置文件。
- Spring 2版本的时候随着JDK1.5注解的出现,Spring的配置转向注解的方式。于是在这个阶段,到底是使用注解的方式来配置还是使用配置文件的方式来配置,最终形成一个共识,对于像数据库配置,事务配置等一些基本配置使用xml,业务配置使用注解。
- 到了Spring3的时代,推荐使用Java进行配置。我们可能对使用xml配置和使用注解的方式配置都比较好理解,而对于使用Java类进行配置感到比较不可思议,我们就以Java配置的方式实现依赖注入。
对于使用XML的方式和注解的方式可能还都比较好理解,使用Java的配置方式确实有些不太好理解,我们把配置放到配置文件中的目的本身就是为了修改配置文件不需要重新编译,现在配置居然告诉我要写到代码里,是不是让人匪夷所思。但是,大家仔细想想,注解是不是也是配置,是不是也是写到代码里了,使用起来是不是很方便。所以在Spring大量的配置中,有一些是不能放到代码里的,比如数据库连接信息,比如web服务的端口等等。但有些是可以放到代码里的,比如bean的配置,再比如切面的配置。所以这么说起来,使用Java进行配置也就好理解了。
刚才提到了,有些配置可以使用配置文件,有些配置不需要使用配置文件,不需要使用配置文件的我们通过使用注解和Java配置的方式可以取代,可能对于刚接触Java配置的朋友还有一个疑问,就是我使用Java配置,我的数据库连接信息怎么办呢?像这种信息依然是配置到配置文件中,Spring提供了便利的EL表达式,可以读取你配置到properties文件中的数据,并且注入到bean中。关于SpringEL到后面会具体的说。到了SpringBoot的时代,直接就给你提供了一个全局的properties文件用于配置。
我们要模拟一个依赖注入,这是我们在使用Spring时非常常见的操作,比如配置数据库连接池等。要模拟依赖注入,至少要有一个生产者,就是服务的提供方,还要有一个消费者,服务的调用方。另外就是一个配置类(取代xml的配置核心类)和一个测试类。下面是代码
服务提供方
服务提供方非常简单,就是一个完全纯净的JavaBean,连注解也都没有了,是不是感觉很清爽!代码完全没有侵入。这里提供了一个sayHello的服务。
public class TestService {
public String sayHello(String name) {
return "Hello " + name;
}
}
服务调用方
服务的调用方也是一个完全纯净的JavaBean,依然非常清爽。这里调用testServce提供的sayHello服务
public class UseTestService {
private TestService testService;
public String sayHello(String name) {
return testService.sayHello(name);
}
public TestService getTestService() {
return testService;
}
public void setTestService(TestService testService) {
this.testService = testService;
}
}
Java配置
@Configuration // 表示这个类是一个配置类
public class JavaConfig {
@Bean // 类似于xml中的<bean>标签,声明一个TestService并交给Spring容器来管理
public TestService testService () {
return new TestService();
}
@Bean // 依赖注入变得非常简答,UserTestService依赖TestService,直接就通过set方法注入了
public UseTestService useTestService() {
UseTestService service = new UseTestService();
service.setTestService(testService());
return service;
}
// 第二种配置注入的方式,直接将依赖的作为参数传递,Spring会自动注入
public UseTestService useTestService(TestService testService) {
UseTestService service = new UseTestService();
service.setTestService(testService);
return service;
}
}
这里是我们的核心配置,在这里我们看到了注解。
@Configuration 表示的是这个类是一个配置类
@Bean 位置是在方法上,表示配置的是一个JavaBean,并将此bean交给spring容器来管理
Configuration 这个注解比较好理解,就是说JavaConfig这个类是一个spring的配置类
Bean这个注解放到了方法上,而方法的返回值就是一个JavaBean对象,也就是说,这里声明了TestService这么一个bean到spring容器中
下面的这个bean,是由spring来管理了服务的消费方,我们知道服务消费方是依赖服务的提供方的,如何解决依赖呢,我们可以看到,首先创建了一个服务的消费方这么一个对象,然后调用set方法将服务的提供方注入,这样就完成了依赖注入。
测试代码
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(JavaConfig.class);
UseTestService service = ac.getBean(UseTestService.class);
System.out.println(service.sayHello("小明"));
ac.close();
}
}
这里就非常简单了,告诉spring配置类,然后从容器中拿到服务的消费方,调用sayHello方法。这个时候,服务的消费方就会调用服务的提供方的sayHello方法,输入我们期望的结果。
上面的这种配置方式非常类似于Spring1时代的xml配置,只是从xml配置变为了Java配置,也并不方便。其实上面的例子依然更适合使用注解的方式进行配置,而对于数据源的配置,事务的配置等等这些可以使用Java的配置方式。
到这里,可能很多朋友会感到疑惑,比如连接数据库的一些连接信息也要写到Java中吗,那岂不是不太好?没错,对于像数据库的连接这样的信息,我们一般仍会使用配置文件的方式进行配置。在Spring3之后,提供了一个非常方便的读取.properties配置文件的注解@PropertySource,并且可以通过@Value注解非常方便的注入配置文件中所保存的数据。
说了这么多,可能对Spring使用注解的配置方式都比较熟悉了,那到底Java配置方式比xml配置方式好在哪呢?
- 实际上也并不能说Java配置就一定比xml配置好,我们从上面的例子中就可以看出来,使用Java的配置方式非常灵活,比如要构建一个非常复杂的对象,那么通过xml的配置可能非常麻烦,而对于使用Java却是非常的容易。
- Java配置是Spring发展的一个趋势,目前比较流行的SpringBoot就抛弃了传统的xml配置的方式
关于Java配置方式,就说到这里,因为企业里一般项目更新进度都比较慢,大部分甚至绝大部分的项目都还在采用xml的配置方式,我个人接触的使用Java配置的项目也并不多,不过,可以预见,未来使用Java的配置方式一定会成为主流。