spring历史
2002年 澳大利亚工程师,rod johnson ,提出了 Srping的概念。
pivotal 团队 在 2014年 推出 spring boot 1.0 版本
2018年 3月 。boot推出,2.0.0 GA版本。基于Spring 5。支持 java 9(最新都用14了)。
springboot实战 引入依赖
<project >
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--里面包含:
spring-boot-starter
spring-boot-starter-json
spring-boot-starter-tomcat
spring-web
spring-webmvc
-->
<!--
spring-boot-starter里面包含:
spring-core
spring-boot-starter-logging
spring-boot-autoconfigure
-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId> //也不需要引用
</plugin>
</plugins>
</build>
</project>
代码
@SpringBootApplication //入口
@Controller //控制器
public class Chapter1Main {
public static void main(String[] args) {
SpringApplication.run(Chapter1Main.class, args);
}
@RequestMapping("/test")//请求
@ResponseBody //json返回
public Map<String, String> test() {
Map<String, String> map = new HashMap<>();
map.put("key1", "value1");
return map;
}
}
第二章 boot +jsp实战
pom
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 没必要引用 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope> 不建议只在编译时候引用
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency><!-- jsp解析 和 jstl -->
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<scope>provided</scope>
</dependency>
<dependency><!-- dbcp2连接池和mysql包 -->
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
application.properties
server.port=8090
spring.mvc.view.prefix=/WEB-INF/jsp/
# src/main/webapp/WEB-INF/jsp/index.jsp index目录,这是eclipse的目录吧
spring.mvc.view.suffix=.jsp
database.driverName=com.mysql.jdbc.Driver
database.url=jdbc:mysql://localhost:3306/test2
database.username=root
database.password=123456
控制器 和视图 和 主方法
@Controller
public class IndexController {
@RequestMapping("/index")
public String index() {
return "index";
}
}
注意 jsp一定放在 main / webapp
src/main/webapp/WEB-INF/jsp/index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Spring boot 视图解析器</title>
</head>
<body>
<h1>测试视图解析器</h1>
</body>
</html>
@SpringBootApplication(scanBasePackages = "com.*")
public class Chapter2Application {
public static void main(String[] args) {
SpringApplication.run(Chapter2Application.class, args);
}
}
第三章,全注解下的spring IOC
Ioc 容器都需要实现接口 BeanFactory。
提供了 通过名字,类型。从Ioc容器 获取bean
是否包含bean
是否单例,原型,是否类型匹配,获取bean的类型,获取bean的别名
默认是单例的, 对应的是 是否原型 isPrototype 如果返回的是true,是原型。getBean Ioc容器就会创建一个新的Bean返回给调用者。
BeanFactory不够强大,spring又设计出 ApplicationContext(子接口),我们使用其实现类。 AnnotationConfigAplicationContext
最简单把自己的类交给spring管理
@Configuration
public class AppConfig {
@Bean(name = "user")
public User initUser(){
User u=new User();
return u;
}
}
ApplicationContext a=new AnnotationConfigApplicationContext(AppConfig.class);
a.getBean(User.class);
扫描装配你的bean
@Componet 哪个类被扫描进入 Spring Ioc容器
@ComponentScan 采用何种策略扫描哦装备Bean
@Component("user")
public class User {
@Value("1")
private Long id;
@Value("user_name_1")
private String userName;
@Value("note_1")
private String note;
}
@Configuration
@ComponentScan(basePackages = "com.springboot.chapter3.*",
public class AppConfig {
}
ApplicationContext a=new AnnotationConfigApplicationContext(AppConfig.class);
a.getBean(User.class);
CompoentScan源码解析
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Repeatable(ComponentScans.class)//在类中可重复定义
public @interface ComponentScan {
@AliasFor("basePackages") //定义扫描的包
String[] value() default {};
@AliasFor("value") //定义扫描的包
String[] basePackages() default {};
Class<?>[] basePackageClasses() default {}; //定义扫描ode类
//bean name生成器
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
//作用域解析器
Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;
//作用域 代理模式
ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;
//资源匹配模式
String resourcePattern() default "**/*.class";
//是否启用默认过滤器
boolean useDefaultFilters() default true;
//满足才会扫描
ComponentScan.Filter[] includeFilters() default {};
//不满足条件才会扫描
ComponentScan.Filter[] excludeFilters() default {};
//是否延迟初始化
boolean lazyInit() default false;
@Retention(RetentionPolicy.RUNTIME)
@Target({})
public @interface Filter { //定义过滤器
FilterType type() default FilterType.ANNOTATION;//过滤类型
@AliasFor("classes") //过滤类
Class<?>[] value() default {};
@AliasFor("value") //过滤类
Class<?>[] classes() default {};
String[] pattern() default {};//匹配方式
}
}
最常用哦的解释
basePackages 定义扫描的包名,默认会扫描当前包,和 其子包下的路径。
includeFilters 满足过滤器 filters条件才会扫描。
excludeFilters 排除过(不满足)滤器条件。通过一个 @Filter 去定义。
@ComponentScan(basePackages = “com.springboot.chapter3.")指定属性名的单个
@ComponentScan( "com.springboot.chapter3.”) 单个
@ComponentScan(basePackages = {“com.springboot.chapter3.*”})数组
@ComponentScan(basePackageClasses = {User.class}) 直接扫描这个类
配置不被装配到:
@Service
public class UserService {
}
@ComponentScan(basePackages = "com.springboot.chapter3.*",
excludeFilters = {@Filter(classes = {UserService.class})})
//UserService将会被排除
@SpringBootApplication 源码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) //自定义排除的两个类
public @interface SpringBootApplication {
@AliasFor(annotation = EnableAutoConfiguration.class)
Class<?>[] exclude() default {};//通过类型 排除自动配置的类
@AliasFor(annotation = EnableAutoConfiguration.class)
String[] excludeName() default {};//通过名称 排除自动配置的类
@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
String[] scanBasePackages() default {}; //定义扫描包
@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
Class<?>[] scanBasePackageClasses() default {}; //定义被扫描的类
}
exclude 和 excludeName 是对内部的自动装配类配置才生效。
我们如果配置扫描user,而不扫扫描 UserService呢? 还是上面的
@SpringBootApplication
@ComponentScan(basePackages = "com.springboot.chapter3.*",
excludeFilters = {@Filter(classes = {Service.clasee})})
自定义第三方bean
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
@Configuration
@ComponentScan(basePackages = "com.springboot.chapter3.*",
excludeFilters = {@Filter(classes = {})})
public class AppConfig {
@Bean(name = "dataSource")
public DataSource getDataSource() {
Properties props = new Properties();
props.setProperty("driver", "com.mysql.jdbc.Driver");
props.setProperty("url", "jdbc:mysql://localhost:3306/chapter3");
props.setProperty("username", "root");
props.setProperty("password", "123456");
DataSource dataSource = null;
try {
dataSource = BasicDataSourceFactory.createDataSource(props);
} catch (Exception e) {
e.printStackTrace();
}
return dataSource;
}
}
使用类 把数据信息存起来
@Component
public class DataBaseProperties {
@Value("${database.driverName}")
private String driverName = null;
@Value("${database.url}")
private String url = null;
private String username = null;
private String password = null;
@Value("${database.username}")
public void setUsername(String username) {
System.out.println(username);
this.username = username;
}
@Value("${database.password}")
public void setPassword(String password) {
System.out.println(password);
this.password = password;
}
}
spring-boot-starter-web
包含: spring-boot-starter , json,tomcat,validator,web,webmvc
spring-boot-starter 中有 spring-boot-autoconfigure, loggin,annotation-api,core,snakeyml
为什么能自动配置:
spring-boot-starter-web中有spring-boot-starter 中有 spring-boot-autoconfigure
源码中 每一个整合的技术都新建了一个文件夹
在web servlet目录下,有DispatcherServletAutoConfiguration 类的内容如下
EnableConfigurationProperties能够在读取配置内容的情况下,生成SpringMVC所需的类,
springBoot通过Maven依赖找到对应的jar包,使用默认的自动配置来创建默认的开发环境
叫做自动装配,开箱即用
DispatcherServletConfiguration源码
@Configuration //指明这是一个配置
@Conditional(DefaultDispatcherServletCondition.class) //配置条件满足DefaultDispatcherServletCondition的验证
@ConditionalOnClass(ServletRegistration.class) //如果存在ServletRegistration则尽心配置
@EnableConfigurationProperties(WebMvcProperties.class) //如果有对应的属性配置,则启用配置,(如:spring.mvc.)
protected static class DispatcherServletConfiguration {
@Bean
@ConditionalOnBean(MultipartResolver.class) //如果存在类定义则配置
@ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME) //如果不存在multipartResolver则配置bean
public MultipartResolver multipartResolver(MultipartResolver resolver) {
return resolver;
}
}
这个类会扫描spring.mvc的配置
@ConfigurationProperties(prefix = "spring.mvc")
public class WebMvcProperties {}
依赖注入 DI
人类通过 动物去 提供一些特殊的服务
public interface Person {
// 使用动物服务
public void service();
// 设置动物
public void setAnimal(Animal animal);
}
public interface Animal {
public void use();
}
@Component
public class Dog implements Animal {
@Override
public void use() {
System.out.println("狗【" + Dog.class.getSimpleName() + "】是看门用的。");
}
}
@Autowired注入
@Component
public class BussinessPerson
implements Person{
@Autowired
private Animal animal = null;
}
测试也可以用 AnnotationConfigApplicationContext
如果在写一个猫类。
- 办法1
@Autowired
private Animal dog = null;
- Autowired 可以为null
@Autowired(required = false)
- 写在方法上
@Override
@Autowired
public void setAnimal(Animal animal) {
this.animal = animal;
}
-
办法二。使用 @Primary 和 @qualifier消除歧义性
- 指定一个优先级
@Component
@Primary //当多个同样类型的bean时,优先使用这个注入
public class Cat implements Animal {}
- 注入给定的bean
@Autowired
@Qualifier("dog")
public void setAnimal(Animal animal) {}
带有构造的方法类的装配
public void BussinessPerson(@Autowired @Qualifier("dog") Animal animal) {}