Spring Boot Bean的装配-六

Spring中的注解
Spring Framework 注解场景说明起始版本
@Repository数据仓储模式注解2.0
@Component通用组件模式注解2.5
@Service服务模式注解2.5
@ControllerWeb 控制器模式注解2.5
@Configuration配置类模式注解3.0

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

装配方式

  • xml

    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"@ComponentScan 方式
    自定义模式注解
    @Component “派生性”
    @Component
    @Repository
    FirstLevelRepository
    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.*.*spring.boot")
public class SpringConfiguration {
...
}
Spring @Enable 模块装配

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

框架实现@Enable 注解模块激活模块
Spring Framework@EnableWebMvcWeb MVC 模块
@EnableTransactionManagement事务管理模块
@EnableCachingCaching 模块
@EnableMBeanExportJMX 模块
@EnableAsync异步处理模块
EnableWebFluxWeb Flux 模块
@EnableAspectJAutoProxyAspectJ 代理模块
Spring Boot@EnableAutoConfiguration自动装配模块
@EnableManagementContextActuator 管理模块
@EnableConfigurationProperties配置属性绑定模块
@EnableOAuth2SsoOAuth2 单点登录模块
实现方式
  • 注解驱动方式

    @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 {
      ...
      }
      
      
      p
      ublic 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;
      }
      }
      

      AdviceModeImportSelector扩展ImportSelecto接口,如果自定义实现只需要实现ImportSelecto接口

      public interface ImportSelector {
      
      	/**
      	 * Select and return the names of which class(es) should be imported based on
      	 * the {@link AnnotationMetadata} of the importing @{@link Configuration} class.
      	 */
      	String[] selectImports(AnnotationMetadata importingClassMetadata);
      
      }
      
  • 自定义 @Enable 模块

    基于注解驱动实现 - @EnableHelloWorld

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    @Documented
    //@Import(HelloWorldConguration.class)
    @Import(HelloWorldImportSelector.class)
    public @interface EnableHelloWorld {
    }
    
    
@Configuration
public class HelloWorldConguration {

    /**
     * 返回值可以是任意类型的
     * @return
     */
    @Bean
    public HelloWorld helloworld(){
        HelloWorld helloWorld = new HelloWorld();
        helloWorld.setAge(18);
        helloWorld.setBirthday(new Date());
        helloWorld.setName("张三");
        return helloWorld;
    }

}
  • Selector实现
/**
 * ImportSelector 实现
 */
public class HelloWorldImportSelector implements ImportSelector{
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        System.err.println(importingClassMetadata.getAnnotationTypes());
        System.err.println(importingClassMetadata.getClassName());
        return new String[]{HelloWorldConguration.class.getName()};
    }
}

Spring 条件装配

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

Spring 注解场景说明起始版本
@Profile配置化条件装配3.1
@Conditional编程条件装配4.0

这里只说Conditional

  • 注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
@Conditional(OnMyUserConditional.class)
public @interface ConditionMyUser {


    String name();

    String value();

}
  • Condition实现

    public class OnMyUserConditional implements Condition {
        @Override
        public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
    
    
            Map<String, Object> attributes = metadata.getAnnotationAttributes(ConditionMyUser.class.getName());
    
    
            if(!attributes.isEmpty()){
    
                String  name = String.valueOf(attributes.get("name"));
    
                String  value = String.valueOf(attributes.get("value"));
    
                return true;
    
            }
    
    
    
            return false;
        }
    }
    
  • Condition接口

    @FunctionalInterface
    public interface Condition {
    
    	boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
    
    }
    
    

测试

public class MyUserBootstarp2 {


    @Bean
    @ConditionMyUser(name = "user.name",value = "就是不知道")
    public String helloUser(){
        return "helloUser "+ LocalDateTime.now();
    }

    public static void main(String[] args) {

        ConfigurableApplicationContext context = new SpringApplicationBuilder(MyUserBootstarp2.class)
                .web(WebApplicationType.NONE)
                .run(args);

        String helloUser = context.getBean("helloUser",String.class);


        System.err.println(helloUser);


        //关闭上下文
        context.close();
    }
}

Spring Boot 自动装配

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

  • Spring 模式注解装配

  • Spring @Enable 模块装配

  • Spring 条件装配装配

  • Spring 工厂加载机制

  • 实现类: SpringFactoriesLoader

  • 配置资源: META-INF/spring.factories

自动装配举例

参考 META-INF/spring.factories

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

在启动类上使用@EnableAutoConfiguration

新建MyUserAutoConfiguration

配置自动装配实现 - META-INF/spring.factories

  1. 条件判断
  2. @Configuration注解
  3. @Enable模块
@Configuration
@EnableMyUser
@ConditionMyUser(name = "user.name",value = "自动装配")
public class MyUserAutoConfiguration {
}


在这里插入图片描述

@EnableAutoConfiguration
public class MyUserAutoConfigurationBootstrap {

    public static void main(String[] args) {

        ConfigurableApplicationContext context = new SpringApplicationBuilder(MyUserAutoConfigurationBootstrap.class)
                .web(WebApplicationType.NONE)
                .run(args);


        MyUser myUser = context.getBean("myUser", MyUser.class);


        System.err.println(myUser.toString());
        context.close();

    }
}

github: https://github.com/ln0491/SpringBootLearning/tree/master/bootlearning

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值