目录
- 一、引出问题(如何配置元数据?)
- 二、没有Spring的时代
- 三、XML配置文件(xml配bean)
- 1 格式
- 1.1 示例
- 2 实例化一个Spring容器
- 3 使用Spring容器
- 4 后言
- 四、基于注解的配置 【[1.9. Annotation-based Container Configuration](https://docs.spring.io/spring-framework/docs/5.2.25.RELEASE/spring-framework-reference/core.html#beans-annotation-config)】
- 1 示例1【applicationContext.scan("...")】
- 2 示例2【通过注解来指定扫描的包】
- 五、基于Java类的配置
- 1 示例
- 六、Spring Boot时代
一、引出问题(如何配置元数据?)
- Java程序可以被简单理解为由bean组成的应用程序。
- 有了Spring后,Spring会负责管理bean,并构建应用的上下文(IoC容器 / Spring容器)。
- Spring怎么知道管理哪些bean呢?
- 那当然是需要开发者提供信息(配置元数据)来告知Spring啊。
- 如何配置元数据呢?(3种方式)【官方文档】
- (1)XML配置文件(xml配bean)
- (2)基于注解的配置
- (3)基于Java类的配置
- 基于Spring的应用:
二、没有Spring的时代
- 示例:
public class Hello {
public void sayHello() {
System.out.println("Hello, World!");
}
}
public class Application {
public static void main(String[] args) {
Hello hello = new Hello();
hello.sayHello();
}
}
- 在使用bean之前,要自己创建,简单情况还好办。
- 一旦类A中依赖类B,类B又依赖类C,这就麻烦了。
- 还是把bean的控制权交给Spring吧(控制反转),让Spring来管理bean,并构建应用上下文。
三、XML配置文件(xml配bean)
1 格式
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>
<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>
<!-- more bean definitions go here -->
</beans>
1.1 示例
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="hello" class="com.forrest.learnspring.springyes.xml.bean.Hello" />
</beans>
2 实例化一个Spring容器
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
- 常见的ApplicationContext的实现:
- (1)ClassPathXmlApplicationContext
- 从classpath中寻找beans.xml,并以该xml文件构建Spring容器。
- (2)FileSystemXmlApplicationContext
- 从文件系统中加载beans.xml文件,并以该xml文件构建Spring容器。
- (3)AnnotationConfigApplicationContext
- 根据注解和Java类构建Spring容器
- (1)ClassPathXmlApplicationContext
3 使用Spring容器
public class Application {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
Hello hello = applicationContext.getBean("hello", Hello.class);
hello.sayHello();
}
}
4 后言
- 基于XML来配置元数据是非常强大的,官方文档也在这方面着墨甚多。
- 然而,除非必须使用XML配置文件,否则Spring官方更推崇基于注解或Java类来配置元数据。
四、基于注解的配置 【1.9. Annotation-based Container Configuration】
- 没有了xml文件,Spring怎么知道要为哪些class创建bean?
- 关键看:class有没有打上如下4个注解:
- @Component
- @Controller
- @Service
- @Repository
当然了,本质是@Component这个注解。例如:@Service这个注解也包含@Component。
- Spring去哪找这些class呢?
- 因此,还需要指定扫描组件的包。
1 示例1【applicationContext.scan(“…”)】
@Component
public class Hello {
public void sayHello() {
System.out.println("Hello, World!");
}
}
public class Application {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.scan("com.forrest.learnspring.springyes.annotation");
applicationContext.refresh();
Hello hello = applicationContext.getBean(Hello.class);
hello.sayHello();
}
}
- 还可以再实例化AnnotationConfigApplicationContext时,指定扫描的包:
public class Application {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext("com.forrest.learnspring.springyes.annotation.example2");
Hello hello = applicationContext.getBean(Hello.class);
hello.sayHello();
}
}
2 示例2【通过注解来指定扫描的包】
@ComponentScan("com.forrest.learnspring.springyes.annotation.example3")
public class Application {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Application.class);
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
Arrays.stream(beanDefinitionNames).forEach(System.out::println);
}
}
/**
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
application
hello
*/
五、基于Java类的配置
- 这种本质是将基于xml的配置翻译为Java代码。
1 示例
public class Hello {
public void sayHello() {
System.out.println("Hello, World!");
}
}
@Configuration
public class HelloConfig {
@Bean
public Hello hello(){
return new Hello();
}
}
@ComponentScan("com.forrest.learnspring.springyes.config.example1")
public class Application {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Application.class);
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
Arrays.stream(beanDefinitionNames).forEach(System.out::println);
}
}
/**
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
application
helloConfig
hello
*/
六、Spring Boot时代
- 为啥还要写
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Application.class);
?这和业务逻辑又没有关系。 - Spring Boot时代,就不用写了!详见:第一次开发基于SpringBoot的Java应用
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
- Spring Boot默认会扫描Application所在的包及其子包的所有bean。
- Spring Boot整合Spring、Spring MVC、MyBatis,轻松搭建一个基于MVC架构的单体web应用。
- 前端调用Http接口,后端的controller接收Http请求。
- 核心业务逻辑由service层完成。
- service层通过dao层获取数据库的数据进行处理。