99uu官方客户端99uu官方客户端

优优官方导航
优优最新网址

一步步从Spring Framework装配掌握SpringBoot自动装配

目录

Spring Framework模式注解Spring Framework@Enable模块装配Spring Framework条件装配SpringBoot 自动装配本章总结

Spring Framework模式注解

模式注解是一种用于声明在应用中扮演“组件”角色的注解。如 Spring Framework 中的 @Repository 标注在任何类上 ,用于扮演仓储角色的模式注解。

模式注解(角色注解)

Spring Framework 注解场景说明
@Component通用组件模式注解
@ControllerWeb 控制器模式注解
@Service服务模式注解
@Repository数据仓储模式注解
@Configuration配置类模式注解

在Spring中进行装配

<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://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@Componentpublic @interface MyServiceAnnotation { String value() default "";}

第二步:将注解作用在自定义Bean上

@MyServiceAnnotation(value = "testBean")public class TestBean { }

第三步:测试是否可以从Spring容器中获取到自定义Bean

@SpringBootApplicationpublic 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@EnableWebMvcWeb MVC 模块
Spring Framework@EnableTransactionManagement事务管理模块
Spring Framework@EnableCachingCaching 模块
Spring Framework@EnableMBeanExportJMX 模块
Spring Framework@EnableAsync异步处理模块
Spring Framework@EnableWebFluxWeb Flux 模块
Spring Framework@EnableAspectJAutoProxy AspectJ代理模块
Spring Boot@EnableAutoConfiguration自动装配模块
Spring Boot@EnableManagementContextActuator 管理模块
Spring Boot@EnableConfigurationProperties配置属性绑定模块
Spring Boot@EnableOAuth2SsoOAuth2 单点登录模块
......

@Enable实现方式

注解驱动方式接口编程方式

实战:自定义@Enable注解驱动实现方式

第一步:实现自定义注解@EnableMyBean

@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Import(MyBeanConfig.class)public @interface EnableMyBean {}

PS:注意@Import(MyBeanConfig.class),将导入MyBeanConfig配置类的相关Bean

第二步:创建MyBeanConfig配置类

@Configurationpublic class MyBeanConfig { @Bean(name = "hello") public String hello() { return "word"; }}

第三步:在应用中测试使用@EnableMyBean

@SpringBootApplication(scanBasePackages = "com.jimisun.learnspringboot.three")@EnableMyBeanpublic 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配置类

@Configurationpublic class MyBeanConfig { @Bean public String hello() { return "word"; }}

第四步:在应用中测试使用@EnableMyBean

@SpringBootApplication(scanBasePackages = "com.jimisun.learnspringboot.four")@EnableMyBeanpublic 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应用中应用条件装配

@SpringBootApplicationpublic 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

@EnableAutoConfigurationpublic 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@EnableMyBeanpublic class HelloWordAutoConfiguration {}

PS:这里使用了上面我们创建的@EnableMyBean,这个注解会注入一个名为“hello"的Bean

第三步:配置自动装配实现 - META-INF/spring.factories

在ClassPath目录下创建META-INF文件夹再创建spring.factories文件

#配置自己的自动装配Beanorg.springframework.boot.autoconfigure.EnableAutoConfiguration=com.jimisun.learnspringboot.five.HelloWordAutoConfiguration

最后:运行测试第一步中的Main方法,看是否能获取到名为“hello”的Bean

本章总结

本章我们主要了解了Spring Framework的模式注解装配,@Enable装配和条件装配。对于SpringBoot的自动装配我们仅仅做了一下演示,遵循SpringBoot装配的三个步骤,我们就可以运行SpringBoot的自动装配。但是对于SpringBoot为什么要遵循这三个步骤?自动装配的原理?我们不知所以然,所以下一章节我们仍然以SpringBoot的自动装配为主题,对SpringBoot的底层源码做剖析。

欢迎阅读本文章: 毛玉霞

优优官方APP

优优官方导航