• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

无信不立

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

【spring-boot】spring-boot学习之ImportSelector接口

一、ImportSelector说明

ImportSelector接口是至spring中导入外部配置的核心接口,在SpringBoot的自动化配置和@EnableXXX(功能性注解)都有它的存在,关于SpringBoot的分析可以参考:https://www.cnblogs.com/niechen/p/9027804.html

其主要作用是收集需要导入的配置类,如果该接口的实现类同时实现EnvironmentAware, BeanFactoryAware ,BeanClassLoaderAware或者ResourceLoaderAware,那么在调用其selectImports方法之前先调用上述接口中对应的方法,如果需要在所有的@Configuration处理完在导入时可以实现DeferredImportSelector接口。

在这里我举个Spring中的实例来看一下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {

    /**
     * Indicate whether subclass-based (CGLIB) proxies are to be created ({@code true}) as
     * opposed to standard Java interface-based proxies ({@code false}). The default is
     * {@code false}. <strong>Applicable only if {@link #mode()} is set to
     * {@link AdviceMode#PROXY}</strong>.
     * <p>Note that setting this attribute to {@code true} will affect <em>all</em>
     * Spring-managed beans requiring proxying, not just those marked with
     * {@code @Transactional}. For example, other beans marked with Spring's
     * {@code @Async} annotation will be upgraded to subclass proxying at the same
     * time. This approach has no negative impact in practice unless one is explicitly
     * expecting one type of proxy vs another, e.g. in tests.
     */
    boolean proxyTargetClass() default false;

    /**
     * Indicate how transactional advice should be applied. The default is
     * {@link AdviceMode#PROXY}.
     * @see AdviceMode
     */
    AdviceMode mode() default AdviceMode.PROXY;

    /**
     * Indicate the ordering of the execution of the transaction advisor
     * when multiple advices are applied at a specific joinpoint.
     * The default is {@link Ordered#LOWEST_PRECEDENCE}.
     */
    int order() default Ordered.LOWEST_PRECEDENCE;

}
View Code

此注解是开启声明式事务的注解,那么它的@Import所导入的类为TransactionManagementConfigurationSelector,那么我们看一下其类图:

由此可知该类实现类ImportSelector接口

 

一、ImportSelector案例

目标:自定义一个自动装配注解,向IOC容器中注入指定的bean

1、自动装配的注解类

package com.boot.annotations;

import com.boot.annotations.importselector.GlobalConfigImport;

import org.springframework.context.annotation.Import;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 
 */
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Target(ElementType.TYPE)
@Import(GlobalConfigImport.class)
public @interface EnableSpringImport {
}
View Code

2、自动装配的注解使用的导入类,即ImportSelector接口的实现类

package com.boot.annotations.importselector;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;

import lombok.extern.slf4j.Slf4j;

/**
 * 
 */
@Slf4j
public class GlobalConfigImport implements ImportSelector, BeanFactoryAware {

    private BeanFactory beanFactory;

    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        for(String a:importingClassMetadata.getAnnotationTypes()){
            log.info("包含的注解有:{}",a);
        }
        return new String[]{GlobalConfigAutoSetting.class.getName()};
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }
}
View Code

3、需要导入的指定bean以及导入该bean的配置算法类。

package com.boot.annotations.importselector;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;

import lombok.extern.slf4j.Slf4j;

/**
 *
 */
@Slf4j
public class GlobalConfigImport implements ImportSelector, BeanFactoryAware {

    private BeanFactory beanFactory;

    /**
     *  包含的注解有:org.springframework.context.annotation.PropertySource
     *  包含的注解有:org.mybatis.spring.annotation.MapperScan
     *  包含的注解有:org.springframework.boot.autoconfigure.SpringBootApplication
     *  包含的注解有:com.boot.annotations.EnableSpringImport
     * @param importingClassMetadata
     * @return
     */
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        for(String a:importingClassMetadata.getAnnotationTypes()){
            log.info("包含的注解有:{}",a);
        }
        return new String[]{GlobalConfigAutoSetting.class.getName()};
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }
}
View Code

4、spring-boot项目的启动类

package com.spring.sxf.study.springtradeweb;

import com.boot.annotations.EnableSpringImport;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.PropertySource;

@PropertySource(value = "classpath:env.properties", encoding="utf-8")
@MapperScan("com.spring.sxf.study.springtradedao.mapper")
@SpringBootApplication(scanBasePackages="com.spring.sxf")
@EnableSpringImport
public class SpringTradeWebApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringTradeWebApplication.class, args);
    }

}
View Code

5、spring项目启动后,验证指定bean是否被导入spring容器的测试类

@Slf4j
@Controller
@RequestMapping("/blog")
public class BlogController implements ApplicationContextAware {

    @Value("${env.envDesc}")
    private String envDesc;


    private ApplicationContext applicationContext;

    @Autowired
    private BlogService blogService;


    @RequestMapping("/env")
    @ResponseBody
    public String testEnv() {
        log.info("current envDesc:{}", envDesc);
        boolean globalConfig= applicationContext.containsBean("globalConfig");
        if(!globalConfig){
            log.info("spring context not have GlobalConfig");
        }else{
            GlobalConfig globalConfig1=applicationContext.getBean(GlobalConfig.class);
            log.info("spring context hasGlobalConfig key:{} ,value:{}",globalConfig1.getKey(),globalConfig1.getValue());
        }
        return envDesc;
    }

@Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext=applicationContext;
    }
}
View Code

 

posted on 2019-10-08 19:42  无信不立  阅读(767)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3