Spring Boot 2.0深度实践之核心技术篇【第二章 走向自动装配】

课程介绍

  • Spring Framework手动装配
  • Spring Boot自动装配
  • 课堂总结

2-2 Spring Framework 手动装配

在这里插入图片描述

<context:component-scan>:Spring2.5的注解

@ComponentScan:Spring3.1的注解
@Component @Service是Spring2.5的注解
@Configuration 是Spring3.0的注解

@Component 作为一种由 Spring 容器托管的通用模式组件,任何被 @Component 标准的组件均为组件扫描的候选对象。类 似地,凡是被 @Component 元标注(meta-annotated)的注解,如 @Service ,当任何组件标注它时,也被视作组件扫 描的候选对象 (派生性)

在这里插入图片描述

装配方式

<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/springcontext.xsd">
 
    <!-- 激活注解驱动特性 -->    
    <context:annotation-config />
    <!-- 找寻被 @Component 或者其派生 Annotation 标记的类(Class),将它们注册为 Spring Bean -->    
    <context:component-scan base-package="com.imooc.dive.in.spring.boot" />
</beans>
@ComponentScan 方式 
@ComponentScan(basePackages = "com.imooc.dive.in.spring.boot") 
public class SpringConfiguration {    ... }

2-3 Spring Framework手动装配自定义模式注解

自定义模式注解

  • @Component “派生性
/** * 一级 {@link Repository @Repository} * * @author <a href="mailto:mercyblitz@gmail.com">Mercy</a> * @since 1.0.0 */ 
@Target({ElementType.TYPE}) 
@Retention(RetentionPolicy.RUNTIME) 
@Documented 
@Repository 
public @interface FirstLevelRepository {
 
    String value() default "";
 
}

@Component
	@Repository
		@FirstLevelRepository
  • @Component “层次性
@Target({ElementType.TYPE}) 
@Retention(RetentionPolicy.RUNTIME) 
@Documented 
@FirstLevelRepository 
public @interface SecondLevelRepository {
 
    String value() default "";
 
}
@Component
	@Repository
		@FirstLevelRepository
			@SecondLevelRepository

自定义注解

注解的成员变量称之为"签名"

2-4 @Enable 模块装配两种方式

  • Spring @Enable 模块装配

Spring Framework 3.1 开始支持”@Enable 模块驱动“。所谓“模块”是指具备相同领域的功能组件集合, 组合所形成一个独立 的单元。比如 Web MVC 模块、AspectJ代理模块、Caching(缓存)模块、JMX(Java 管 理扩展)模块、Async(异步处 理)模块等。

在这里插入图片描述

@Enable 注解模块举例

在这里插入图片描述

实现方式

注解驱动方式
@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.TYPE) 
@Documented 
@Import(DelegatingWebMvcConfiguration.class) 
public @interface EnableWebMvc { 
}
@Configuration 
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {    ... 
}
接口编程方式
@Target(ElementType.TYPE) 
@Retention(RetentionPolicy.RUNTIME) 
@Documented 
@Import(CachingConfigurationSelector.class) 
public @interface EnableCaching { ... }

public class CachingConfigurationSelector extends AdviceModeImportSelector<EnableCaching> {   
 /**   
  * {@inheritDoc}    
  * @return {@link ProxyCachingConfiguration} or {@code    AspectJCacheConfiguration} for    * {@code PROXY} and {@code ASPECTJ} values of {@link    EnableCaching#mode()}, respectively   
  *  */    
  public String[] selectImports(AdviceMode adviceMode) {        
  	switch (adviceMode) {            
  		case PROXY:                
  			return new String[] { AutoProxyRegistrar.class.getName(),ProxyCachingConfiguration.class.getName() };        
  		case ASPECTJ:            
  			return new String[] {                AnnotationConfigUtils.CACHE_ASPECT_CONFIGURATION_CLASS_NAME };        		
  		default:            
  			return null;    
  	} 
}

@configuration和@component之间的区别

@configuration和@component之间的区别是:@Component注解的范围最广,所有类都可以注解,但是@Configuration注解一般注解在这样的类上:这个类里面有@Value注解的成员变量和@Bean注解的方法,就是一个配置类。

@component多例的,@configuration是单例的

2-5 Spring条件装配

  • 从 Spring Framework 3.1 开始,允许在 Bean 装配时增加前置条件判断

在这里插入图片描述

条件注解举例

在这里插入图片描述

实现方式
配置方式 - @Profile
编程方式 - @Conditional
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME) 
@Documented 
@Conditional(OnClassCondition.class)
public @interface ConditionalOnClass {
 
   /**    * The classes that must be present. Since this annotation is parsed by loading class    * bytecode, it is safe to specify classes here that may ultimately not be on the    * classpath, only if this annotation is directly on the affected component and    * <b>not</b> if this annotation is used as a composed, meta-annotation. In order to    * use this annotation as a meta-annotation, only use the {@link #name} attribute.    * @return the classes that must be present    */ 
     Class<?>[] value() default {};
 
   /**    * The classes names that must be present.
    * @return the class names that must be present.    
    * */   
    String[] name() default {};
 
}

2-6 基于配置方式实现自定义条件装配

基于配置方式实现 - @Profile

计算服务,多整数求和 sum

@Prole("Java7") : for 循环
@Prole("Java8") : Lambda
  • Calculate.java
public interface Calculate {
    int calculate(Integer ... nums);
}
  • JDK7Calculate .java
public class JDK7Calculate implements Calculate {
    @Override
    public int calculate(Integer... nums) {
        System.out.println("JDK7 的计算方法");
        int sum = 0;
        for (Integer i : nums) {
            sum += i;
        }
        return sum;
    }
}

  • JDK8Calculate.java
import java.util.stream.Stream;

public class JDK8Calculate implements Calculate {
    @Override
    public int calculate(Integer... nums) {
        System.out.println("JDK8 的计算方法");
        return Stream.of(nums).reduce(0,Integer::sum);
    }
}
  • CalculateConfiguration .java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;

@Configuration
public class CalculateConfiguration {

    @Profile("JDK7")
    @Bean
    public Calculate getJDK7Caculate(){
        return new JDK7Calculate();
    }



    @Profile("JDK8")
    @Bean
    public Calculate getJDK8Caculate(){
        return new JDK8Calculate();
    }
}
  • Application.java
@SpringBootApplication
public class Application {
    public static void main(String[] args) {


        ConfigurableApplicationContext context = new SpringApplicationBuilder(Application.class)
                .profiles("JDK7")
                .run(args);
        Calculate calculate = context.getBean(Calculate.class);
        int sum = calculate.calculate(8,9,10);
        System.out.println(sum);
    }
}

2-7 基于编程方式实现条件装配

基于编程方式实现 - @ConditionalOnSystemProperty
  • OnSystemPropertyCondition.java
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;

import java.util.Map;

public class OnSystemPropertyCondition implements Condition {
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        Map<String, Object> propertyMap =  annotatedTypeMetadata.getAnnotationAttributes(ConditionalOnSystemProperty.class.getName());
        String name = (String) propertyMap.get("name");
        String value = (String) propertyMap.get("value");
        String systemValue = System.getProperty(name);

        //systemValue = conditionContext.getEnvironment().getProperty(name);

        return value.equals(systemValue);
    }
}
  • @ConditionalOnSystemProperty.java

import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Conditional;

import java.lang.annotation.*;
/**
* 参考 {@link ConditionalOnProperty}
* */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Documented
@Conditional({OnSystemPropertyCondition.class})
public @interface ConditionalOnSystemProperty {

    String name() default "";

    String value() default "";
}
  • SystemPropertyBootstrap.java
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;


public class SystemPropertyBootstrap {

    @Bean
    @ConditionalOnSystemProperty(name = "user.name",value = "Dell")
    public String helloWorld(){
        return "Hello Everyone";
    }

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SystemPropertyBootstrap.class);

        String value  = (String) context.getBean("helloWorld");
        System.out.println(value);
    }
}

2-8 Spring Boot 自动装配

在这里插入图片描述

在 Spring Boot 场景下,基于约定大于配置的原则,实现 Spring 组件自动装配的目的。其中使用了

  • 底层装配技术
  • Spring 模式注解装配

  • Spring @Enable 模块装配

  • Spring 条件装配装配

  • Spring 工厂加载机制

    • 实现类:SpringFactoriesLoader
    • 配置资源: META-INF/spring.factories
  • 自动装配举例
  • 参考 META-INF/spring.factorie

  • 自定义自动装配
  • HelloWorldAutoConfiguration

    • 条件判断: user.name == "Mercy"
    • 模式注解: @Configuration
    • @Enable 模块: @EnableHelloWorld -> HelloWorldImportSelector -> HelloWorldConfiguration - > helloWorld

2-9 自定义自动装配

  • 实现方法
    1. 激活自动装配 @EnableAutoConfiguration
    1. 实现自动装配 - XXXAutoConfiguration
    1. 配置自动装配实现 - META-INF/spring.factories

Application.java

package com.example.test2_9;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {

        ConfigurableApplicationContext context = new SpringApplicationBuilder(Application.class)
               .run(args);

        String hello = (String) context.getBean("whaleson");
        System.out.println(hello);
    }

}

HelloWorldAutoConfiguration2_9.java

package com.example.test2_9;


import com.example.demo.annotation.EnableHelloWorldAnnotation;
import com.example.demo.conditional.ConditionalOnSystemProperty;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableHelloWorldAnnotation
@ConditionalOnSystemProperty(name = "user.name",value = "Dell")
public class HelloWorldAutoConfiguration2_9 {
}

HelloWorldConfiguration2_9.java

package com.example.test2_9;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class HelloWorldConfiguration2_9 {

    @Bean(name = "whaleson")
    public String getHello(){
        return "Hello World,Hello Everybody.";
    }
}

HelloWorldImportSelector2_9.java

package com.example.test2_9;

import com.example.demo.configuration.HelloWorldConfiguration;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;

public class HelloWorldImportSelector2_9 implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        return new String []{HelloWorldConfiguration.class.getName()};
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
SpringBoot是企业级开发的整体整合解决方案,特别用于快速构建微服务应用,旨在用最简单的方式让开发人员适应各种开发场景; 本视频着重介绍SpringBoot的使用和内部原理;内容包含微服务概念、配置文件、日志框架的使用、web开发、Thymeleaf模板引擎、Docker容器技术、MyBatis、Spring Data JPA、自定义starter等; 00、尚硅谷_SpringBoot_源码、课件 01、尚硅谷_SpringBoot_入门-课程简介 02、尚硅谷_SpringBoot_入门-Spring Boot简介 03、尚硅谷_SpringBoot_入门-微服务简介 04、尚硅谷_SpringBoot_入门-环境准备 05、尚硅谷_SpringBoot_入门-springboot-helloworld 06、尚硅谷_SpringBoot_入门-HelloWorld细节-场景启动器(starter) 07、尚硅谷_SpringBoot_入门-HelloWorld细节-自动配置 08、尚硅谷_SpringBoot_入门-使用向导快速创建Spring Boot应用 09、尚硅谷_SpringBoot_配置-yaml简介 10、尚硅谷_SpringBoot_配置-yaml语法 11、尚硅谷_SpringBoot_配置-yaml配置文件值获取 12、尚硅谷_SpringBoot_配置-properties配置文件编码问题 13、尚硅谷_SpringBoot_配置-@ConfigurationProperties与@Value区别 14、尚硅谷_SpringBoot_配置-@PropertySource、@ImportResource、@Bean 15、尚硅谷_SpringBoot_配置-配置文件占位符 16、尚硅谷_SpringBoot_配置-Profile多环境支持 17、尚硅谷_SpringBoot_配置-配置文件的加载位置 18、尚硅谷_SpringBoot_配置-外部配置加载顺序 19、尚硅谷_SpringBoot_配置-自动配置原理 20、尚硅谷_SpringBoot_配置-@Conditional&自动配置报告 21、尚硅谷_SpringBoot_日志-日志框架分类和选择 22、尚硅谷_SpringBoot_日志-slf4j使用原理 23、尚硅谷_SpringBoot_日志-其他日志框架统一转换为slf4j 24、尚硅谷_SpringBoot_日志-SpringBoot日志关系 25、尚硅谷_SpringBoot_日志-SpringBoot默认配置 26、尚硅谷_SpringBoot_日志-指定日志文件和日志Profile功能 27、尚硅谷_SpringBoot_日志-切换日志框架 28、尚硅谷_SpringBoot_web开发-简介 29、尚硅谷_SpringBoot_web开发-webjars&静态资源映射规则 30、尚硅谷_SpringBoot_web开发-引入thymeleaf 31、尚硅谷_SpringBoot_web开发-thymeleaf语法 32、尚硅谷_SpringBoot_web开发-SpringMVC自动配置原理 33、尚硅谷_SpringBoot_web开发-扩展与全面接管SpringMVC 34、尚硅谷_SpringBoot_web开发-【实验】-引入资源 35、尚硅谷_SpringBoot_web开发-【实验】-国际化 36、尚硅谷_SpringBoot_web开发-【实验】-登陆&拦截器 37、尚硅谷_SpringBoot_web开发-【实验】-Restful实验要求 38、尚硅谷_SpringBoot_web开发-【实验】-员工列表-公共页抽取 39、尚硅谷_SpringBoot_web开发-【实验】-员工列表-链接高亮&列表完成 40、尚硅谷_SpringBoot_web开发-【实验】-员工添加-来到添加页面 41、尚硅谷_SpringBoot_web开发-【实验】-员工添加-添加完成 42、尚硅谷_SpringBoot_web开发-【实验】-员工修改-重用页面&修改完成 43、尚硅谷_SpringBoot_web开发-【实验】-员工删除-删除完成 44、尚硅谷_SpringBoot_web开发-错误处理原理&定制错误页面 45、尚硅谷_SpringBoot_web开发-定制错误数据 46、尚硅谷_SpringBoot_web开发-嵌入式Servlet容器配置修改 47、尚硅谷_SpringBoot_web开发-注册servlet三大组件 48、尚硅谷_SpringBoot_web开发-切换其他嵌入式Servlet容器 49、尚硅谷_SpringBoot_web开发-嵌入式Servlet容器自动配置原理 50、尚硅谷_SpringBoot_web开发-嵌入式Servlet容器启动原理 51、尚硅谷_SpringBoot_web开发-使用外部Servlet容器&JSP;支持 52、尚硅谷_SpringBoot_web开发-外部Servlet容器启动SpringBoot应用原理 53、尚硅谷_SpringBoot_Docker-简介 54、尚硅谷_SpringBoot_Docker-核心概念 55、尚硅谷_SpringBoot_Docker-linux环境准备 56、尚硅谷_SpringBoot_Docker-docker安装&启动&停止 57、尚硅谷_SpringBoot_Docker-docker镜像操作常用命令 58、尚硅谷_SpringBoot_Docker-docker容器操作常用命令 59、尚硅谷_SpringBoot_Docker-docker安装MySQL 60、尚硅谷_SpringBoot_数据访问-简介 61、尚硅谷_SpringBoot_数据访问-JDBC&自动配置原理 62、尚硅谷_SpringBoot_数据访问-整合Druid&配置数据源监控 63、尚硅谷_SpringBoot_数据访问-整合MyBatis(一)-基础环境搭建 64、尚硅谷_SpringBoot_数据访问-整合MyBatis(二)-注解版MyBatis 65、尚硅谷_SpringBoot_数据访问-整合MyBatis(二)-配置版MyBatis 66、尚硅谷_SpringBoot_数据访问-SpringData JPA简介 67、尚硅谷_SpringBoot_数据访问-整合JPA 68、尚硅谷_SpringBoot_原理-第一步:创建SpringApplication 69、尚硅谷_SpringBoot_原理-第二步:启动应用 70、尚硅谷_SpringBoot_原理-事件监听机制相关测试 71、尚硅谷_SpringBoot_原理-自定义starter

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值