第二章:走向自动装配

第一节:Spring Framework 手动装配

第二节:Spring Framework 手动装配自定义模式注解

spirng 模式注解装配
定义
  • 一种用于声明在应用(Spring 或Spring boot中)中扮演“组件”角色的注解
举例
  • @Component @Service @Controller @Configuration
1.@Service @Controller @Repository这三个注解从源码上看其实都是@Component 实现的,所以本质上这三个没有什么区别。

通常地,@Service @Controller @Repository是为了给不同的类打上不同的标志来区别开各个类的作用是什么,

@Service表明是一个服务

@Controller表明是一个控制器

@Repository表明是一个仓储,说明是数据库访问模型

如果该类没有明确定义是服务、控制器、仓储,可以用@Component标明
@Component 作为spring容器托管的通用模式组件,任何被它附加的组件,都会被容器作为组件扫描对象
2.@Autowired

首先spring是一个约定大于配置的框架,变量的名字对于注入的对象是有影响的 
@Autowired
private Book book;

其次需要注意的是接口不可以用@Component,也没有意义,提到的bean都是具体的class类

① @Autowired优先按bytype查找并实例化,没有找到任何一个bean,会报错
② 按bytype找到多个,会按byname找,如果仍没找到,会报错(byname查找方式可以用@Qualifier,@Qualifier声明的byname变量优先级最高)
③ 在成员变量注入和setter注入的时候必须加上@Autowired,在构造器注入的时候可以不加,直接按原来的方式写构造器把实例当参数传进去即可,spring官方推荐构造函数注入或setter注入,因为两种是对public做注入

3.@Configuration

是在spring3.0里加入的新特性,通常在写框架的时候被用到,是配置类注解,用来解决变化的问题,很重要
@Configuration主要是用来取代xml配置方式的
装配方式
  • <context:component-scan>
<beans>
激活注解驱动特性
<context:annotation-config />
寻找被@Component 或者派生注解标记的类class,将他们注册为 spring bean
<context:component-scan base-package="com.lc.springboot" />
</beans>
  • @ComponentScan
@ComponentScan(basePackages = "com.lc.springboot")
public class SpringConfiguration{
	...
}

第三节:@Enable 模块装配两种方式

定义
  • 具备相同领域的功能组件集合,组合所形成一个独立的单元
举例
  • @EnableWebMvc -web MVC模块
  • @EnableAutoConfiguration - 自动装配模块
  • @EnableEurekaServer - Eureka 服务器模块
实现
注解驱动方式
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc{   
}

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

public class CachingConfigurationSelector extends AdviceModeImportSelector<EnableCaching>{
    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;    
    }
}

public class AdviceModeImportSelector implements ImportSelector{
    
}

第四节:Spring条件装配

定义
  • Bean装配的前置判断(条件装配也属于spring framework 手动装配一种)
举例
  • @Profile - 配置化条件装配
  • @Contitional - 编程条件装配

实现

  • 基于配置方式实现 - @Profile
  • 计算服务,多整数求和Sum
  • @Profile("java7") for循环
  • @Profile("java8") lambda表达式
public interface Calculate {
    //变量参数
    Integer sum(Integer... values);
}
@Profile("java7")
@Service
public class Java7Calculate implements Calculate {
    public Integer sum(Integer... values) {
        System.out.println("java7");
        int sum = 0;
        for (Integer value : values) {
            sum += value;
        }
        return sum;
    }

    public static void main(String[] args) {
        Java7Calculate java7Calculate = new Java7Calculate();
        System.out.println(java7Calculate.sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
    }
}
@Profile("java8")
@Service
public class Java8Calculate implements Calculate{
    public Integer sum(Integer... values) {
        System.out.println("java8");
        int sum = Stream.of(values).reduce(0, Integer::sum);
        return sum;
    }
    public static void main(String[] args) {
        Java8Calculate java8Calculate = new Java8Calculate();
        System.out.println(java8Calculate.sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
    }
}
/*
*  启动类
*/
//两种包扫描方式都可以实现
@SpringBootApplication(scanBasePackages = "com.lc.service")
//@ComponentScan(basePackages = "com.lc.service")
public class CalculateBootstrap {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = new SpringApplicationBuilder(CalculateBootstrap.class)
                .web(WebApplicationType.NONE)
                .profiles("java8")//指定当前容器使用哪个profile
                .run(args);
        //判断Bean是否存在
        Calculate calculate = context.getBean(Calculate.class);
        System.out.println(calculate.sum(1,2,3,4,5,6,7,8,9,10));
        //关闭上下文
        context.close();
    }
}
  • 基于编程方式实现 - @ConditionalOnProperty
/**
* 自定义注解
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Documented
@Conditional({OnMyPropertyCondition.class})
public @interface MyConditionalOnProperty {
    String value();

    String name();

}
/*
* 实现注解,同时编程进行各种判断
*/
public class OnMyPropertyCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Map<String, Object> attributes = metadata.getAnnotationAttributes(MyConditionalOnProperty.class.getName());
        String name = (String) attributes.get("name");
        String value = (String) attributes.get("value");
        String javaValue = System.getProperty(name);//获取系统用户信息,也可以从配置文件中读取
        System.out.println(javaValue);
        return value.equals(javaValue); //输入值和系统用户名相同,则返回
    }
}
/*
* 条件装配,启动类,
*/
public class OnMyPropertyConditionBootstrap {
    //创建个Bean,使用条件装配,如果value相同,才会注入IOC容器
    @Bean
    @MyConditionalOnProperty(name = "user.name",value = "2466")
    public String helloWorld(){
        return "hello,world";
    }
    
    public static void main(String[] args) {
        ConfigurableApplicationContext context = new SpringApplicationBuilder(OnMyPropertyConditionBootstrap.class)
                .web(WebApplicationType.NONE)//web应用类型,Servlet、Reactive、None,第三章推断web类型详解源码
                .run(args);

        String bean = context.getBean("helloWorld",String.class);//使用context上下文,获取配置对应的Bean,在value相同时,可以获取,在value不同时,则会报错,容器中没有该Bean
        System.out.println(bean);
        //关闭上下文
        context.close();
    }
}

第五节:Spring Boot 自动装配

定义
  • 基于规约大于配置,实现spirng组件自动装配的目的
底层装配方式
  • Spirng模式注解
  • Spirng @Enable模块
  • Spirng条件装配
  • Spirng工厂加载机制
  • 实现类 SpringFactoriesLoader
  • 配置资源 META-INF/spring.factories
实现步骤
  1. 激活自动装配 - @EnableAutoConfiguration
  2. 实现自动装配 - XXXAutoConfiguration
  3. 配置自动装配实现 - META/INFO/spring.factories