查看“SpringBoot:快速入门”的源代码
←
SpringBoot:快速入门
跳到导航
跳到搜索
因为以下原因,您没有权限编辑本页:
您请求的操作仅限属于该用户组的用户执行:
用户
您可以查看和复制此页面的源代码。
[[category:SpringBoot]] == Spring的发展 == # Spring1.x: #: 通过'''xml文件'''配置bean:随着项目的不断扩大,需要将xml配置分放到不同的配置文件中,需要频繁的在java类和xml配置文件中切换。 # Spring2.x: #:(JDK 1.5 注解支持)使用'''注解'''对Bean进行申明和注入:大大的减少了xml配置文件,同时也大大简化了项目的开发。 ## 应用的基本配置用xml(如:数据源、资源文件等); ## 业务开发用注解(如:Service中注入bean等); # Spring3.x(Spring4.x): #: 推荐使用'''Java配置'''方式:可以完全替代xml配置。 === Spring的Java配置方式 === (Java配置是Spring4.x推荐的配置方式)<br/> Spring的Java配置方式是通过 @Configuration 和 @Bean 这两个注解实现的: # '''@Configuration''':标记类,相当于一个xml配置文件; # '''@Bean''':标记方法,相当于xml配置中的“<bean>”; 其他配置类注解: # 读取外部的资源配置文件: ## '''@PropertySource''':指定读取的配置文件; ## '''@Value''':获取配置文件的配置项; 示例:配置数据库连接池: ::<syntaxhighlight lang="java"> // 通过该注解来表明该类是一个Spring的配置,相当于一个xml文件 @Configuration // 配置扫描包,相当于xml中的"<context:component-scan ...>" @ComponentScan(basePackages = "cn.itcast.springboot.javaconfig") //加载配置文件 @PropertySource(value = { "classpath:jdbc.properties", "xxx.properties" }, ignoreResourceNotFound = true) public class SpringConfig { @Bean // 通过该注解来表明是一个Bean对象,相当于xml中的<bean> //1、相当于xml中的<bean>标签 //2、相当于类中的@Service类的注解 //所以"UserDAO"可以用于"UserService"属性注入 public UserDAO getUserDAO() { return new UserDAO(); // 直接new对象做演示 } //返回值,相当于<bean>中的"class"属性 //方法名称,相当于<bean>中的"id"属性? // 获取配置文件的配置项 @Value("${jdbc.url}") private String jdbcUrl; @Value("${jdbc.driverClassName}") private String jdbcDriverClassName; @Value("${jdbc.username}") private String jdbcUsername; @Value("${jdbc.password}") private String jdbcPassword; @Bean(destroyMethod = "close") public DataSource dataSource() { BoneCPDataSource boneCPDataSource = new BoneCPDataSource(); // 数据库驱动 boneCPDataSource.setDriverClass(jdbcDriverClassName); // 相应驱动的jdbcUrl boneCPDataSource.setJdbcUrl(jdbcUrl); // 数据库的用户名 boneCPDataSource.setUsername(jdbcUsername); // 数据库的密码 boneCPDataSource.setPassword(jdbcUsername); // 检查数据库连接池中空闲连接的间隔时间,单位是分,默认值:240,如果要取消则设置为0 boneCPDataSource.setIdleConnectionTestPeriodInMinutes(60); // 连接池中未使用的链接最大存活时间,单位是分,默认值:60,如果要永远存活设置为0 boneCPDataSource.setIdleMaxAgeInMinutes(30); // 每个分区最大的连接数 boneCPDataSource.setMaxConnectionsPerPartition(100); // 每个分区最小的连接数 boneCPDataSource.setMinConnectionsPerPartition(5); return boneCPDataSource; } } </syntaxhighlight> === 实例 === # 创建工程以及导入依赖: #: <syntaxhighlight lang="xml"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>cn.itcast.springboot</groupId> <artifactId>itcast-springboot</artifactId> <version>1.0.0-SNAPSHOT</version> <packaging>war</packaging> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.3.7.RELEASE</version> </dependency> <!-- 连接池 --> <dependency> <groupId>com.jolbox</groupId> <artifactId>bonecp-spring</artifactId> <version>0.8.0.RELEASE</version> </dependency> </dependencies> <build> <finalName>${project.artifactId}</finalName> <plugins> <!-- 资源文件拷贝插件 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <configuration> <encoding>UTF-8</encoding> </configuration> </plugin> <!-- java编译插件 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.7</source> <target>1.7</target> <encoding>UTF-8</encoding> </configuration> </plugin> </plugins> <pluginManagement> <plugins> <!-- 配置Tomcat插件 --> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> </plugin> </plugins> </pluginManagement> </build> </project> </syntaxhighlight> # 编写User对象: #: <syntaxhighlight lang="java"> public class User { private String username; private String password; private Integer age; // getter & setter & toString } </syntaxhighlight> # 编写UserDao接口: #: <syntaxhighlight lang="java"> public interface UserDao { //根据id查询用户信息 public User findUserById(int id) throws Exception; } </syntaxhighlight> # 编写UserDaoImpl接口:(mybatis) #: <syntaxhighlight lang="java"> public class UserDaoImpl implements UserDao { // 需要向dao实现类中注入SqlSessionFactory // 这里通过构造方法注入 private SqlSessionFactory sqlSessionFactory; public UserDaoImpl(SqlSessionFactory sqlSessionFactory) { this.sqlSessionFactory = sqlSessionFactory; } @Override public User findUserById(int id) throws Exception { SqlSession sqlSession = sqlSessionFactory.openSession(); User user = sqlSession.selectOne("test.findUserById", id); // 释放资源 sqlSession.close(); return user; } } </syntaxhighlight> # 编写UserService实现User数据操作业务逻辑: #: <syntaxhighlight lang="java"> @Service public class UserService { @Autowired // 注入Spring容器中的bean对象 private UserDaoImpl UserDaoImpl; public User findUserById(int id) throws Exception { // 调用userDAO中的方法进行查询 return this.UserDaoImpl.findUserById(id); } } </syntaxhighlight> # 编写SpringConfig用于'''实例化Spring容器''': #: <syntaxhighlight lang="java" highlight="1-2,5"> @Configuration //通过该注解来表明该类是一个Spring的配置,相当于一个xml文件 @ComponentScan(basePackages = "cn.itcast.springboot.javaconfig") //配置扫描包 public class SpringConfig { @Bean // 通过该注解来表明是一个Bean对象,相当于xml中的<bean> public UserDao getUserDao(){ return new UserDao(); // 直接new对象做演示 } } </syntaxhighlight> # 编写测试方法,'''启动Spring容器''': #: <syntaxhighlight lang="java"> public class Main { public static void main(String[] args) { // 使用xml方式的“加载spring配置文件” ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml"); // 对比使用:通过Java配置来实例化Spring容器 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); // 使用xml方式的“根据配置创建对象” UserService userService = (UserService) context.getBean("userService"); // 对比使用:在Spring容器中获取Bean对象 UserService userService = context.getBean(UserService.class); // 调用对象中的方法 List<User> list = userService.queryUserList(); for (User user : list) { System.out.println(user.getUsername() + ", " + user.getPassword() + ", " + user.getPassword()); } // 销毁该容器 context.destroy(); } } </syntaxhighlight> === 实例化Spring容器:xml与Java配置 === 对比,“xml、注解”于“Java配置类”的实例化Spring容器: <syntaxhighlight lang="java"> // 通过Java配置来实例化Spring容器 // 1、Java配置类 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); // 2、xml、注解 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); // 在Spring容器中“获取Bean对象” // 1、Java配置类 UserService userService = context.getBean(UserService.class); // 2、xml、注解 UserService userService = (UserService) context.getBean("userService"); </syntaxhighlight> == Spring Boot == “习惯优于配置”:<br/> SpringBoot是一种全新的框架,目的是为了简化Spring应用的初始搭建以及开发过程。该框架使用特定的方式(集成starter,约定优于配置)来进行配置,从而使开发人员不需要再定义样板化的配置。 * SpringBoot基于Sring4进行设计,继承了原有Spring框架的优秀基因。 * SpringBoot并不是一个框架,而是一些类库的集合。 * maven或者gradle项目导入相应依赖即可使用SpringBoot,而无需自行管理这些类库的版本。 优点: # 快速创建基于Spring的应用程序。 # 无需手动管理依赖包的版本。 # 自动配置,无需XML。 # 嵌入式的Tomcat,无需部署war文件。 === 快速入门 === ==== 设置spring boot的parent ==== <syntaxhighlight lang="xml"> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.2.RELEASE</version> </parent> </syntaxhighlight> Spring boot的项目必须要将parent设置为spring boot的parent,该parent包含了大量默认的配置,大大简化了我们的开发。 ==== 导入spring boot的web支持 ==== <syntaxhighlight lang="xml"> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> </syntaxhighlight> ==== 添加Spring boot的插件 ==== <syntaxhighlight lang="xml"> <build> <finalName>${project.artifactId}</finalName> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> <pluginManagement> ... </pluginManagement> </build> </syntaxhighlight> ==== 编写第一个Spring Boot的应用 ==== <syntaxhighlight lang="java"> @Controller @SpringBootApplication @Configuration public class HelloApplication { @RequestMapping("hello") @ResponseBody public String hello(){ return "hello world!"; } public static void main(String[] args) { SpringApplication.run(HelloApplication.class, args); } } </syntaxhighlight> # '''@SpringBootApplication''':Spring Boot项目的核心注解,主要目的是开启自动配置; # '''@Configuration''':这是一个配置Spring的配置类; # '''@Controller''':标明这是一个SpringMVC的Controller控制器; # main方法:在main方法中启动一个应用,即:这个应用的入口; ==== 启动应用 ==== 在Spring Boot项目中,启动的方式有两种,一种是另外一种是。 # 直接run Java Application #: [[File:SpringBoot启动应用:RunAS ”Java Aplication“.png|600px]] # 通过Spring Boot的Maven插件运行 #: [[File:SpringBoot启动应用:Maven插件运行.png|600px]] == SpringBoot核心 == === 入口类和@SpringBootApplication === Spring Boot的项目一般都会有“xxxApplication”的入口类,类中有main方法,这是一个标准的Java应用程序的入口方法。<br/> <syntaxhighlight lang="java"> @Controller @SpringBootApplication(exclude = { RedisAutoConfiguration.class }) @Configuration public class HelloApplication { public static void main(String[] args) { SpringApplication.run(HelloApplication.class, args); } } </syntaxhighlight> 其中:“'''@SpringBootApplication'''”:是Spring Boot的核心注解,它其实是一个组合注解: <syntaxhighlight lang="java"> @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 { </syntaxhighlight> # “'''@SpringBootConfiguration'''”:Spring Boot项目的'''配置'''注解(组合注解): #: <syntaxhighlight lang="java"> @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Configuration public @interface SpringBootConfiguration { } </syntaxhighlight> #* 在Spring Boot中推荐使用“@SpringBootConfiguration”替代“@Configuration”; # “'''@EnableAutoConfiguration'''”:'''启用自动配置''',该注解会使Spring Boot根据项目中依赖的jar包自动配置项目的配置项: # “'''@ComponentScan'''”:默认扫描“@SpringBootApplication”所在类的同级目录,以及它的子目录; === 关闭自动配置 === 启用自动配置时,Spring Boot会根据项目中的jar包依赖,自动做出配置;而Spring Boot支持的自动配置如下(非常多): :[[File:SpringBoot启动应用:自动配置.png|400px]] 如果不需要Spring Boot自动配置,想关闭某一项的自动配置(以Redis为例): <syntaxhighlight lang="java"> @Controller @SpringBootApplication(exclude = { RedisAutoConfiguration.class }) @Configuration public class HelloApplication { </syntaxhighlight> === 自定义Banner === 启动Spring Boot项目后会看到默认的Banner: :[[File:SpringBoot启动应用:Banner.png|600px]] * 关闭Banner: *: <syntaxhighlight lang="java"> public static void main(String[] args) { // SpringApplication.run(HelloApplication.class, args); SpringApplication application = new SpringApplication(HelloApplication.class); application.setBannerMode(Mode.OFF); application.run(args); } </syntaxhighlight> * 自定义Banner: *# 在[http://patorjk.com/software/taag/#p=display&h=3&v=3&f=4Max&t=itcast%20Spring%20Boot 工具站点]中生成Banner,并保存为“banner.txt”; *# 将banner.txt拷贝到项目的resources目录; *#: [[File:SpringBoot启动应用:Banner自定义.png|200px]] === 全局配置文件 === Spring Boot项目使用一个全局的配置文件“application.properties”(或“application.yml”),在“resources”目录下(或:类路径下的“/config”下)。<br/> 可以进行项目全局配置,如: : <syntaxhighlight lang="properties"> server.port=8088 server.servlet-path=/ spring.resources.static-locations=classpath:/public/ logging.level.org.springframework=DEBUG </syntaxhighlight> * 更多配置:'''[[SpringBoot全局配置]]''' === Starter pom === Starter POMs是可以包含到应用中的一个方便的“依赖关系描述符集合”。 * 可以通过starters获取所有Spring及相关技术的一站式服务,而不需要翻阅示例代码,拷贝粘贴大量的依赖描述符; * 所有的starters遵循一个相似的命名模式:“'''spring-boot-starter-*'''”; 例如:在 SpringBoot 项目中集成 Redis,那么我只需要加入“spring-data-redis-starter”的依赖: <syntaxhighlight lang="xml"> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> </syntaxhighlight> 而不需考虑与其他内容的依赖、版本等; 官方支持的 starter pom:(2.3.5.RELEASE) {| class="wikitable" ! 名称 !! 描述 |- ! colspan="2"| application starters |- | spring-boot-starter || Core starter, including auto-configuration support, logging and YAML |- | spring-boot-starter-activemq || Starter for JMS messaging using Apache ActiveMQ |- | spring-boot-starter-amqp || Starter for using Spring AMQP and Rabbit MQ |- | spring-boot-starter-aop || Starter for aspect-oriented programming with Spring AOP and AspectJ |- | spring-boot-starter-artemis || Starter for JMS messaging using Apache Artemis |- | spring-boot-starter-batch || Starter for using Spring Batch |- | spring-boot-starter-cache || Starter for using Spring Framework’s caching support |- | spring-boot-starter-data-cassandra || Starter for using Cassandra distributed database and Spring Data Cassandra |- | spring-boot-starter-data-cassandra-reactive || Starter for using Cassandra distributed database and Spring Data Cassandra Reactive |- | spring-boot-starter-data-couchbase || Starter for using Couchbase document-oriented database and Spring Data Couchbase |- | spring-boot-starter-data-couchbase-reactive || Starter for using Couchbase document-oriented database and Spring Data Couchbase Reactive |- | spring-boot-starter-data-elasticsearch || Starter for using Elasticsearch search and analytics engine and Spring Data Elasticsearch |- | spring-boot-starter-data-jdbc || Starter for using Spring Data JDBC |- | spring-boot-starter-data-jpa || Starter for using Spring Data JPA with Hibernate |- | spring-boot-starter-data-ldap || Starter for using Spring Data LDAP |- | spring-boot-starter-data-mongodb || Starter for using MongoDB document-oriented database and Spring Data MongoDB |- | spring-boot-starter-data-mongodb-reactive || Starter for using MongoDB document-oriented database and Spring Data MongoDB Reactive |- | spring-boot-starter-data-neo4j || Starter for using Neo4j graph database and Spring Data Neo4j |- | spring-boot-starter-data-r2dbc || Starter for using Spring Data R2DBC |- | spring-boot-starter-data-redis || Starter for using Redis key-value data store with Spring Data Redis and the Lettuce client |- | spring-boot-starter-data-redis-reactive || Starter for using Redis key-value data store with Spring Data Redis reactive and the Lettuce client |- | spring-boot-starter-data-rest || Starter for exposing Spring Data repositories over REST using Spring Data REST |- | spring-boot-starter-data-solr || Starter for using the Apache Solr search platform with Spring Data Solr |- | spring-boot-starter-freemarker || Starter for building MVC web applications using FreeMarker views |- | spring-boot-starter-groovy-templates || Starter for building MVC web applications using Groovy Templates views |- | spring-boot-starter-hateoas || Starter for building hypermedia-based RESTful web application with Spring MVC and Spring HATEOAS |- | spring-boot-starter-integration || Starter for using Spring Integration |- | spring-boot-starter-jdbc || Starter for using JDBC with the HikariCP connection pool |- | spring-boot-starter-jersey || Starter for building RESTful web applications using JAX-RS and Jersey. An alternative to spring-boot-starter-web |- | spring-boot-starter-jooq || Starter for using jOOQ to access SQL databases. An alternative to spring-boot-starter-data-jpa or spring-boot-starter-jdbc |- | spring-boot-starter-json || Starter for reading and writing json |- | spring-boot-starter-jta-atomikos || Starter for JTA transactions using Atomikos |- | spring-boot-starter-jta-bitronix || Starter for JTA transactions using Bitronix. Deprecated since 2.3.0 |- | spring-boot-starter-mail || Starter for using Java Mail and Spring Framework’s email sending support |- | spring-boot-starter-mustache || Starter for building web applications using Mustache views |- | spring-boot-starter-oauth2-client || Starter for using Spring Security’s OAuth2/OpenID Connect client features |- | spring-boot-starter-oauth2-resource-server || Starter for using Spring Security’s OAuth2 resource server features |- | spring-boot-starter-quartz || Starter for using the Quartz scheduler |- | spring-boot-starter-rsocket || Starter for building RSocket clients and servers |- | spring-boot-starter-security || Starter for using Spring Security |- | spring-boot-starter-test || Starter for testing Spring Boot applications with libraries including JUnit, Hamcrest and Mockito |- | spring-boot-starter-thymeleaf || Starter for building MVC web applications using Thymeleaf views |- | spring-boot-starter-validation || Starter for using Java Bean Validation with Hibernate Validator |- | spring-boot-starter-web || Starter for building web, including RESTful, applications using Spring MVC. Uses Tomcat as the default embedded container |- | spring-boot-starter-web-services || Starter for using Spring Web Services |- | spring-boot-starter-webflux || Starter for building WebFlux applications using Spring Framework’s Reactive Web support |- | spring-boot-starter-websocket || Starter for building WebSocket applications using Spring Framework’s WebSocket support |- ! colspan="2"| production starters |- | spring-boot-starter-actuator || Starter for using Spring Boot’s Actuator which provides production ready features to help you monitor and manage your application |- ! colspan="2"| technical starters |- | spring-boot-starter-jetty || Starter for using Jetty as the embedded servlet container. An alternative to spring-boot-starter-tomcat |- | spring-boot-starter-log4j2 || Starter for using Log4j2 for logging. An alternative to spring-boot-starter-logging |- | spring-boot-starter-logging || Starter for logging using Logback. Default logging starter |- | spring-boot-starter-reactor-netty || Starter for using Reactor Netty as the embedded reactive HTTP server. |- | spring-boot-starter-tomcat || Starter for using Tomcat as the embedded servlet container. Default servlet container starter used by spring-boot-starter-web |- | spring-boot-starter-undertow || Starter for using Undertow as the embedded servlet container. An alternative to spring-boot-starter-tomcat |} === Xml 配置文件 === # “'''@PropertySource'''”:加载指定的配置文件; #* 只能加载“*.properties”文件,不能加载“.yaml”文件; #: <syntaxhighlight lang="java"> @PropertySource(value = { "classpath:jdbc.properties" }, ignoreResourceNotFound = true) </syntaxhighlight> # “'''@Import'''”: #* 4.2之前,只支持导入配置类;(相当于“<import resource=""/>”标签) #* 4.2之后,支持导入普通的java类,并将其声明成一个bean; #: <syntaxhighlight lang="java"> @Import({ CustomerConfig.class, SchedulerConfig.class }) </syntaxhighlight> # “'''@ImportResource'''”:导入Spring的配置文件,让配置文件里面的内容生效; #* SpringBoot中编写的Spring配置文件是不能自动识别的;【???】 #: <syntaxhighlight lang="java"> @ImportResource(locations = {"classpath:applicationContext.xml"}) </syntaxhighlight> === 日志 === Spring Boot对各种日志框架都做了支持,可以通过全局配置来修改默认的日志的配置: <syntaxhighlight lang="properties"> #设置日志级别 logging.level.*= # Log levels severity mapping. For instance `logging.level.org.springframework=DEBUG` </syntaxhighlight> == 自动配置的原理 == Spring Boot在进行SpringApplication对象实例化时会加载“META-INF/spring.factories”文件,将该配置文件中的配置载入到Spring容器。 * “META-INF/spring.factories”文件,位于“'''spring-boot-autoconfigure-1.5.2.RELEASE.jar'''”包中,而非项目路径下; *: [[File:spring-boot-autoconfigure-1.5.2.RELEASE包中.jpg|400px]] * 全局配置“application.properties”(“application.yml”)时,需要的配置项,可以根据jar包(“org.springframework.boot.autoconfigure”)下对应包中的自动配置类得出; *: 如下面的 Redis的自动配置; === spring.factories 的加载 === 配置文件“spring.factories”的读取,是在“org.springframework.boot.SpringApplication”的初始化方法中进行的: : <syntaxhighlight lang="java" line highlight="9,15,20"> public class SpringApplication { ... @SuppressWarnings({ "unchecked", "rawtypes" }) private void initialize(Object[] sources) { if (sources != null && sources.length > 0) { this.sources.addAll(Arrays.asList(sources)); } this.webEnvironment = deduceWebEnvironment(); setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)); setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); this.mainApplicationClass = deduceMainApplicationClass(); } ... private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type) { return getSpringFactoriesInstances(type, new Class<?>[] {}); } private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) { ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); // Use names and ensure unique to protect against duplicates Set<String> names = new LinkedHashSet<String>(SpringFactoriesLoader.loadFactoryNames(type, classLoader)); List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names); AnnotationAwareOrderComparator.sort(instances); return instances; } ... } </syntaxhighlight> “org.springframework.core.io.support.SpringFactoriesLoader”: : <syntaxhighlight lang="java" line highlight="3,8"> public abstract class SpringFactoriesLoader { ... public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories"; ... public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) { String factoryClassName = factoryClass.getName(); try { Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) : ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION)); List<String> result = new ArrayList<String>(); while (urls.hasMoreElements()) { URL url = urls.nextElement(); Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url)); String factoryClassNames = properties.getProperty(factoryClassName); result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames))); } return result; } catch (IOException ex) { throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() + "] factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex); } } ... } </syntaxhighlight> === 示例:Redis的自动配置 === 由“spring.factories”文件: <syntaxhighlight lang="properties" highlight="4"> # Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ ... org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\ ... </syntaxhighlight> 可知“org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration”是Redis的自动配置: :[[File:spring-boot:RedisAutoConfiguration.jpg|300px]] <syntaxhighlight lang="java"> @Configuration @ConditionalOnClass({ JedisConnection.class, RedisOperations.class, Jedis.class }) @EnableConfigurationProperties(RedisProperties.class) public class RedisAutoConfiguration { @Configuration @ConditionalOnClass(GenericObjectPool.class) protected static class RedisConnectionConfiguration { private final RedisProperties properties; private final RedisSentinelConfiguration sentinelConfiguration; private final RedisClusterConfiguration clusterConfiguration; ... } @Configuration protected static class RedisConfiguration { @Bean @ConditionalOnMissingBean(name = "redisTemplate") public RedisTemplate<Object, Object> redisTemplate( RedisConnectionFactory redisConnectionFactory) throws UnknownHostException { RedisTemplate<Object, Object> template = new RedisTemplate<Object, Object>(); template.setConnectionFactory(redisConnectionFactory); return template; } @Bean @ConditionalOnMissingBean(StringRedisTemplate.class) public StringRedisTemplate stringRedisTemplate( RedisConnectionFactory redisConnectionFactory) throws UnknownHostException { StringRedisTemplate template = new StringRedisTemplate(); template.setConnectionFactory(redisConnectionFactory); return template; } } } </syntaxhighlight> # 内部类“RedisConnectionConfiguration”:Redis连接设置; #* “RedisProperties”:Redis配置类; # 内部类“RedisConfiguration”:获取RedisTemplate; * “RedisProperties”: *:<syntaxhighlight lang="java"> @ConfigurationProperties(prefix = "spring.redis") public class RedisProperties { /** * Database index used by the connection factory. */ private int database = 0; /** * Redis url, which will overrule host, port and password if set. */ private String url; /** * Redis server host. */ private String host = "localhost"; /** * Login password of the redis server. */ private String password; ... } </syntaxhighlight> *# “(prefix = "spring.redis")”:配置项的前缀(匹配SpringBoot全局配置文件中的前缀); *# “database”、“url”等:配置项; === 条件注解 === SpringBoot内部提供了特有的注解:条件注解(Conditional Annotation);<br/> 条件注解存在的意义在于动态识别(也可以说是代码自动化执行)。比如@ConditionalOnClass会检查类加载器中是否存在对应的类,如果有的话被注解修饰的类就有资格被Spring容器所注册,否则会被skip。 {| class="wikitable" ! 条件注解 ! 对应的Condition处理类 ! 说明 |- | @ConditionalOnBean || OnBeanCondition | Spring容器中是否存在对应的实例。 * 可以通过实例的类型、类名、注解、昵称去容器中查找; * (可以配置从当前容器中查找或者父容器中查找或者两者一起查找); * 这些属性都是数组,通过”与”的关系进行查找; <syntaxhighlight lang="java"> @ConditionalOnBean(javax.sql.DataSource.class) // Spring容器或者所有父容器中需要存在至少一个javax.sql.DataSource类的实例 </syntaxhighlight> |- | @ConditionalOnClass || OnClassCondition | 类加载器中是否存在对应的类。 * 可以通过Class指定(value属性)或者Class的全名指定(name属性); * 如果是多个类或者多个类名的话,关系是”与”关系,也就是说这些类或者类名都必须同时在类加载器中存在; <syntaxhighlight lang="java"> @ConditionalOnClass({ Configuration.class, FreeMarkerConfigurationFactory.class }) // 类加载器中必须存在 Configuration和 FreeMarkerConfigurationFactory这两个类 </syntaxhighlight> |- | @ConditionalOnExpression || OnExpressionCondition | 判断SpEL 表达式是否成立 <syntaxhighlight lang="java"> @ConditionalOnExpression("'${server.host}'=='localhost'") // server.host配置项的值需要是localhost </syntaxhighlight> |- | @ConditionalOnJava || OnJavaCondition | 指定Java版本是否符合要求。 * 内部有2个属性“value”和“range”: *# value表示一个枚举的Java版本, *# range表示比这个老或者新于等于指定的Java版本(默认是新于等于)。 * 内部会基于某些jdk版本特有的类去类加载器中查询,比如: *# 如果是jdk9,类加载器中需要存在“java.security.cert.URICertStoreParameters”; *# 如果是jdk8,类加载器中需要存在“java.util.function.Function”; *# 如果是jdk7,类加载器中需要存在“java.nio.file.Files”; *# 如果是jdk6,类加载器中需要存在“java.util.ServiceLoader” <syntaxhighlight lang="java"> ConditionalOnJava(JavaVersion.EIGHT) // Java版本至少是8 </syntaxhighlight> |- | @ConditionalOnMissingBean || OnBeanCondition | Spring容器中是否缺少对应的实例。 * 可以通过实例的类型、类名、注解、昵称去容器中查找 *: (可以配置从当前容器中查找或者父容器中查找或者两者一起查找) * 这些属性都是数组,通过”与”的关系进行查找。 * 还多了2个属性ignored(类名)和ignoredType(类名),匹配的过程中会忽略这些bean <syntaxhighlight lang="java"> @ConditionalOnMissingBean(value = ErrorController.class, search = SearchStrategy.CURRENT) // Spring当前容器中不存在ErrorController类型的bean </syntaxhighlight> |- | @ConditionalOnMissingClass || OnClassCondition | 跟ConditionalOnClass的处理逻辑一样,只是条件相反,在类加载器中不存在对应的类 <syntaxhighlight lang="java"> @ConditionalOnMissingClass("GenericObjectPool") // 类加载器中不能存在GenericObjectPool这个类 </syntaxhighlight> |- | @ConditionalOnNotWebApplication || OnWebApplicationCondition | 应用程序是否是非Web程序,没有提供属性,只是一个标识。 * 会从判断Web程序特有的类是否存在,环境是否是Servlet环境,容器是否是Web容器等 <syntaxhighlight lang="java"> @ConditionalOnNotWebApplication // 必须在非Web应用下才会生效 </syntaxhighlight> |- | @ConditionalOnProperty || OnPropertyCondition | 应用环境中的屬性是否存在。 * 提供“prefix”、“name”、“havingValue”以及“matchIfMissing”属性。 *: prefix:属性名的前缀, *: name:属性名, *: havingValue:具体的属性值, *: matchIfMissing:(boolean值)如果属性不存在,这个matchIfMissing为true的话,会继续验证下去,否则属性不存在的话直接就相当于匹配不成功; <syntaxhighlight lang="java"> @ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true) // 应用程序的环境中必须有spring.aop.auto这项配置,且它的值是true或者环境中不存在spring.aop.auto配置(matchIfMissing为true) </syntaxhighlight> |- | @ConditionalOnResource || OnResourceCondition | 是否存在指定的资源文件。 * 只有一个属性resources,是个String数组。会从类加载器中去查询对应的资源文件是否存在; <syntaxhighlight lang="java"> @ConditionalOnResource(resources="mybatis.xml") // 类加载路径中必须存在mybatis.xml文件 </syntaxhighlight> |- | @ConditionalOnSingleCandidate || OnBeanCondition | Spring容器中是否存在且只存在一个对应的实例。 * 只有3个属性“value”、“type”、“search”,跟ConditionalOnBean中的这3种属性值意义一样 <syntaxhighlight lang="java"> @ConditionalOnSingleCandidate(PlatformTransactionManager.class) // Spring当前或父容器中必须存在PlatformTransactionManager这个类型的实例,且只有一个实例 </syntaxhighlight> |- | @ConditionalOnWebApplication || OnWebApplicationCondition | 应用程序是否是Web程序,没有提供属性,只是一个标识。 * 会从判断Web程序特有的类是否存在,环境是否是Servlet环境,容器是否是Web容器等 <syntaxhighlight lang="java"> @ConditionalOnWebApplication // 必须在Web应用下才会生效 </syntaxhighlight> |} === Maven下载源码 === 通过“dependency:sources”命令,可以下载该项目中所有的依赖的包的源码。
返回至“
SpringBoot:快速入门
”。
导航菜单
个人工具
登录
命名空间
页面
讨论
大陆简体
已展开
已折叠
查看
阅读
查看源代码
查看历史
更多
已展开
已折叠
搜索
导航
首页
最近更改
随机页面
MediaWiki帮助
笔记
服务器
数据库
后端
前端
工具
《To do list》
日常
阅读
电影
摄影
其他
Software
Windows
WIKIOE
所有分类
所有页面
侧边栏
站点日志
工具
链入页面
相关更改
特殊页面
页面信息