一步步从Spring Framework装配掌握SpringBoot自动装配
Spring Framework模式注解
模式注解是一种用于声明在应用中扮演“组件”角色的注解。如 Spring Framework 中的 @Repository 标注在任何类上 ,用
于扮演仓储角色的模式注解。
模式注解(角色注解)
| Spring Framework 注解 | 场景说明 |
|---|---|
| @Component | 通用组件模式注解 |
| @Controller | Web 控制器模式注解 |
| @Service | 服务模式注解 |
| @Repository | 数据仓储模式注解 |
| @Configuration | 配置类模式注解 |
在Spring中进行装配context:component-scan 方式
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-
context.xsd">
<!-- 激活注解驱动特性 -->
<context:annotation-config />
<!-- 找寻被 @Component 或者其派生 Annotation 标记的类(Class),将它们注册为 Spring Bean -->
<context:component-scan base-package="com.imooc.dive.in.spring.boot" />
</beans>
在Spring中基于Java注解配置方式
@ComponentScan(basePackages = "com.imooc.dive.in.spring.boot")
public class SpringConfiguration {
...
}
实战:自定义模式注解
@Component 模式注解具有“派生性”和“层次性”,我们能够自定义创建Bean注解
第一步:自定义SpringBean注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface MyServiceAnnotation {
String value() default "";
}
第二步:将注解作用在自定义Bean上
@MyServiceAnnotation(value = "testBean")
public class TestBean {
}
第三步:测试是否可以从Spring容器中获取到自定义Bean
@SpringBootApplication
public class Main {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(Main.class, args);
TestBean testBean = run.getBean("testBean", TestBean.class);
System.out.println("testBean" + testBean.toString());
run.close();
}
}
Spring Framework@Enable模块装配
Spring Framework 3.1 开始支持”@Enable 模块驱动“。所谓“模块”是指具备相同领域的功能组件集合, 组合所形成一个独立的单元。比如 Web MVC 模块、AspectJ代理模块、Caching(缓存)模块、JMX(Java 管 理扩展)模块、Async(异步处理)模块等。
@Enable 注解模块举例
| 框架实现 | @Enable 注解模块 | 激活模块 |
|---|---|---|
| Spring Framework | @EnableWebMvc | Web MVC 模块 |
| Spring Framework | @EnableTransactionManagement | 事务管理模块 |
| Spring Framework | @EnableCaching | Caching 模块 |
| Spring Framework | @EnableMBeanExport | JMX 模块 |
| Spring Framework | @EnableAsync | 异步处理模块 |
| Spring Framework | @EnableWebFlux | Web Flux 模块 |
| Spring Framework | @EnableAspectJAutoProxy AspectJ | 代理模块 |
| Spring Boot | @EnableAutoConfiguration | 自动装配模块 |
| Spring Boot | @EnableManagementContext | Actuator 管理模块 |
| Spring Boot | @EnableConfigurationProperties | 配置属性绑定模块 |
| Spring Boot | @EnableOAuth2Sso | OAuth2 单点登录模块 |
| ...... |
@Enable实现方式
- 注解驱动方式
- 接口编程方式
实战:自定义@Enable注解驱动实现方式
第一步:实现自定义注解@EnableMyBean
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(MyBeanConfig.class)
public @interface EnableMyBean {
}
PS:注意@Import(MyBeanConfig.class),将导入MyBeanConfig配置类的相关Bean
第二步:创建MyBeanConfig配置类
@Configuration
public class MyBeanConfig {
@Bean(name = "hello")
public String hello() {
return "word";
}
}
第三步:在应用中测试使用@EnableMyBean
@SpringBootApplication(scanBasePackages = "com.jimisun.learnspringboot.three")
@EnableMyBean
public class Main {
public static void main(String[] args) {
ConfigurableApplicationContext context =
new SpringApplicationBuilder(Main.class)
.web(WebApplicationType.NONE)
.run(args);
String bean = context.getBean("hello", String.class);
context.close();
}
}
实战:自定义@Enable接口实现方式
第一步:实现自定义注解@EnableMyBean
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(MyBeanConfigSelector.class)
public @interface EnableMyBean {
}
PS:注意@Import(MyBeanConfigSelector.class)导入的类和@Enable注解驱动导入的不一样,这里导入的是一个实现了ImportSelector接口的类
public class MyBeanConfigSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
return new String[]{new MyBeanConfig().getClass().getName()};
}
}
PS:在MyBeanConfigSelector类中我们可以自定义复杂的逻辑,这里我们仅仅简单返回MyBeanConfig配置类。
第三步:创建MyBeanConfig配置类
@Configuration
public class MyBeanConfig {
@Bean
public String hello() {
return "word";
}
}
第四步:在应用中测试使用@EnableMyBean
@SpringBootApplication(scanBasePackages = "com.jimisun.learnspringboot.four")
@EnableMyBean
public class Main {
public static void main(String[] args) {
ConfigurableApplicationContext context =
new SpringApplicationBuilder(Main.class)
.web(WebApplicationType.NONE)
.run(args);
String bean = context.getBean("hello", String.class);
context.close();
}
}
PS:其实@Enable接口的实现方式和@Enable注解实现方式是基本一样的,只不过多了一个步骤,方便我们更灵活地进行编写逻辑。
Spring Framework条件装配
从 Spring Framework 3.1 开始,允许在 Bean 装配时增加前置条件判断
| Spring 注解 | 场景说明 | 起始版本 |
|---|---|---|
| @Profile | 配置化条件装配 | 3.1 |
| @Conditional | 编程条件装配 | 4.0 |
实战:自定义@Profile 配置化条件装配
第一步:自定义创建某服务不同的@Profile实现类
public interface UserService {
void println();
}
@Service
@Profile("vip")
public class VipUserservice implements UserService {
@Override
public void println() {
System.out.println("I am VIP User");
}
}
@Service
@Profile("common")
public class CommonUserservice implements UserService {
@Override
public void println() {
System.out.println("I am Common User");
}
}
第二步:在构建Spring容器指定配置
@ComponentScan(basePackages = "com.jimisun.learnspringboot.two")
public class Main {
public static void main(String[] args) {
ConfigurableApplicationContext run = new SpringApplicationBuilder(Main.class).
web(WebApplicationType.NONE).
profiles("vip").
run(args);
UserService bean = run.getBean(UserService.class);
bean.println();
run.close();
}
}
实战:自定义@Conditional 编程条件装配
第一步:创建一个自定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Documented
@Conditional({MyOnConditionProperty.class})
public @interface MyConditionOnPropertyAnnotion {
String prefix() default "";
}
PS:注意@Conditional注解,将会找到MyOnConditionProperty类的matches方法进行条件验证
第二步:创建该注解的条件验证类,该类实现Condition接口
public class MyOnConditionProperty implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
Map<String, Object> annotationAttributes =
annotatedTypeMetadata.getAnnotationAttributes(MyConditionOnPropertyAnnotion.class.getName());
String prefix = String.valueOf(annotationAttributes.get("prefix"));
return prefix.equals("pass");
}
}
第三步:在Spring应用中应用条件装配
@SpringBootApplication
public class Main {
@Bean(name = "hello")
@MyConditionOnPropertyAnnotion(prefix = "pass")
public String hello() {
return "word";
}
public static void main(String[] args) {
ConfigurableApplicationContext context =
new SpringApplicationBuilder(Main.class)
.web(WebApplicationType.NONE)
.run(args);
String bean = context.getBean("hello", String.class);
context.close();
}
}
PS:本例自定义的MyConditionOnPropertyAnnotion在应用中装配的时候可以指定prefix值,该值将会在实现了Condition借口的matches进行条件验证,如果验证通过,则在Spring容器中装配该Bean,反之则不装配。
SpringBoot 自动装配
在 Spring Boot 场景下,基于约定大于配置的原则,实现 Spring 组件自动装配的目的。其中底层使用了一系列的Spring Framework手动装配的方法来构成Spring Boot自动装配。
自定义SpringBoot自动装配
- 激活自动装配 - @EnableAutoConfiguration
- 实现自动装配 - XXXAutoConfiguration
- 配置自动装配实现 - META-INF/spring.factories
第一步 :激活自动装配 - @EnableAutoConfiguration
@EnableAutoConfiguration
public class Main {
public static void main(String[] args) {
ConfigurableApplicationContext context =
new SpringApplicationBuilder(Main.class)
.web(WebApplicationType.NONE)
.run(args);
String bean = context.getBean("hello", String.class);
context.close();
}
}
第二步:实现自动装配 - XXXAutoConfiguration
@Configuration
@EnableMyBean
public class HelloWordAutoConfiguration {
}
PS:这里使用了上面我们创建的@EnableMyBean,这个注解会注入一个名为“hello"的Bean
第三步:配置自动装配实现 - META-INF/spring.factories
在ClassPath目录下创建META-INF文件夹再创建spring.factories文件
#配置自己的自动装配Bean
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.jimisun.learnspringboot.five.HelloWordAutoConfiguration
最后:运行测试第一步中的Main方法,看是否能获取到名为“hello”的Bean
本章总结
本章我们主要了解了Spring Framework的模式注解装配,@Enable装配和条件装配。对于SpringBoot的自动装配我们仅仅做了一下演示,遵循SpringBoot装配的三个步骤,我们就可以运行SpringBoot的自动装配。但是对于SpringBoot为什么要遵循这三个步骤?自动装配的原理?我们不知所以然,所以下一章节我们仍然以SpringBoot的自动装配为主题,对SpringBoot的底层源码做剖析。
该教程所属Java工程师之SpringBoot系列教程,本系列相关博文目录 Java工程师之SpringBoot系列教程前言&目录
一步步从Spring Framework装配掌握SpringBoot自动装配的更多相关文章
- Spring Boot之从Spring Framework装配掌握SpringBoot自动装配
Spring Framework模式注解 模式注解是一种用于声明在应用中扮演“组件”角色的注解.如 Spring Framework 中的 @Repository 标注在任何类上 ,用于扮演仓储角色的 ...
- SpringBoot源码学习1——SpringBoot自动装配源码解析+Spring如何处理配置类的
系列文章目录和关于我 一丶什么是SpringBoot自动装配 SpringBoot通过SPI的机制,在我们程序员引入一些starter之后,扫描外部引用 jar 包中的META-INF/spring. ...
- SpringBoot启动流程分析(五):SpringBoot自动装配原理实现
SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...
- SpringBoot学习(三)探究Springboot自动装配
目录 什么是自动装配 何时自动装配 原理分析 注:以下展示的代码springboot的版本为2.0.3版.因源码过长,大家选择展开代码 ㄟ( ▔, ▔ )ㄏ 什么是自动装配 自动装配还是利用了Spri ...
- springboot自动装配
Spring Boot自动配置原理 springboot自动装配 springboot配置文件 Spring Boot的出现,得益于“习惯优于配置”的理念,没有繁琐的配置.难以集成的内容(大多数流行第 ...
- springboot自动装配(1)---@SpringBootApplication注解怎么自动装配各种组件
1.对于springboot个人认为它就是整合了各种组件,然后提供对应的自动装配和启动器(starter) 2.@SpringBootApplication注解其实就是组合注解,通过它找到自动装配的注 ...
- springboot自动装配(3)---条件注解@Conditional
之前有说到springboot自动装配的时候,都是去寻找一个XXXAutoConfiguration的配置类,然而我们的springboot的spring.factories文件中有各种组件的自动装配 ...
- SpringBoot自动装配原理解析
本文包含:SpringBoot的自动配置原理及如何自定义SpringBootStar等 我们知道,在使用SpringBoot的时候,我们只需要如下方式即可直接启动一个Web程序: @SpringBoo ...
- springboot自动装配redis在pool下偶尔出现连接异常的问题
jedis pool的配置其实是采用 org.apache.commons.pool2.impl.GenericObjectPoolConfig类的配置项. jedis 2.9版本代码如下: pack ...
随机推荐
- delete指针以后应赋值为NULL——QT deletelater指针以后也同样要马上赋值为NULL
delete p后,只是释放了指针指向的内存空间.p并不会自动被置为NULL,而且指针还在,同时还指向了之前的地址 delete NULL编译器不会报错(因为delete空指针是合法的) 例: 对一个 ...
- python中的高阶函数
高阶函数英文叫Higher-order function.什么是高阶函数?我们以实际代码为例子,一步一步深入概念. 变量可以指向函数 以Python内置的求绝对值的函数abs()为例,调用该函数用以下 ...
- C Language Study - 函数指针的使用
函数指针的使用 1.函数指针定义 第一次使用函数指针,我是这样声明的,typedef void ( *pSimulatepks )( uint8 *prxBuf, uint8 *prxBufLen ) ...
- Linux新手要了解的十个知识点
Linux对于有的新手来说,感觉无从下手,或者不知道从哪儿学起?怎么学?针对这些问题,我给大家说说新手学习Linux需要了解的十个知识点. 注意大小写 Linux是大小写敏感的系统,举个例子,Mozi ...
- jQuery实现HTML表格单元格的合并功能
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- Maven------使用maven新建web项目出现问题 项目名称出现红色交叉
转载: http://wenda.so.com/q/1365963640069173?src=140 解决方法: problems窗口查看到下面错误java compiler level does n ...
- swift--控件工厂类的实现
控件工厂类,简而言之就是,减少代码的复用率,只在哪里用,然后在哪里调: 代码如下: import UIKit class ViewFactory: UIView,UITextFieldDelegate ...
- swift -- 计步器CMPedometer的使用
最近公司接了个项目,是一款运动类型的APP,可以检测运动量(例如:步数,上下楼等).睡眠信息.速度等信息,因为以前粗略的了解过传感器方面的相关信息,知道主要是苹果设备内置的传感器在起作用,传感器的种类 ...
- GIS-012-ArcGIS JS API 绘图
Name Description ARROW Draws an arrow. CIRCLE Draws a circle. DOWN_ARROW Draws an arrow that points ...
- Python 处理命令行参数
optparse模块用于从命令行直接读取参数,用法基本与 argparse模块 一致,如下: #!/usr/bin/env python #-*- coding:utf-8 -*- from optp ...