Spring源码解读 --- 重要注解/组件

(一)@Conditional

- 用在方法上:按照一定的条件进行判断,满足条件给容器中注册bean。
- 用在类上:按照一定的条件进行判断,满足条件才会加载这个类中的所有信息。
@Conditional(WindowCondition.class)
@Bean("maotao")
public Person test01() {
    return new Person("毛涛",21);
}
// 判断条件
public class WindowCondition implements Condition {
    /**
     *
     * @param conditionContext   条件上下文
     * @param annotatedTypeMetadata 注解信息
     * @return
     */
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        // 可以使用的组件
        ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();
        ClassLoader classLoader = conditionContext.getClassLoader();
        BeanDefinitionRegistry registry = conditionContext.getRegistry();
        ResourceLoader resourceLoader = conditionContext.getResourceLoader();
        Environment environment = conditionContext.getEnvironment();
        // 获取操作系统名称
        String environmentName = environment.getProperty("os.name");
        // 判断容器中是否有bean,也可以注册bean
        boolean zhangsan = registry.containsBeanDefinition("zhangsan");
        if (!zhangsan) {
            System.out.println("容器中没有张三");
        }else{
            // 注册张三
            //registry.registerBeanDefinition("zhangsan",new B);
        }
        // 判断环境变量
        if (environmentName.contains("Windows")) {
            return true;
        }
        return false;
    }

(二)@Lazy

懒加载,将单例的bean实例化方式改为懒加载,只有在第一次调用时才加载。

    @Lazy
    @Bean("person")
    public Person test(){
        System.out.println("正在创建:::::");
        return new Person("wagnsan",20);
    }

(三)@Scope

Spring设置bean在IOC容器中的作用域,默认是单例。

// prototype :多实例
// singleton : 单实例
// request :同一次请求创建一个实例
// session : 同一个session创建一个实例
//@Scope(value = "prototype")
@Lazy
@Bean("person")
public Person test(){
    System.out.println("正在创建:::::");
    return new Person("wagnsan",20);
}

(四)@ComponentScan

指定要扫描的包。

  • value是指定要扫描的包路径。

  • 使用includeFilters,需要更改useDefaultFilters=false,禁用默认的过滤。

  • type 是选择过滤类型。

    • ANNOTATION, 注解类型
      ASSIGNABLE_TYPE,指定类型
      ASPECTJ,ASPECTJ表达式
      REGEX,正则表达式
      CUSTOM;自定义类型  
      
@ComponentScan(value = "com.mt",includeFilters = {
        //@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class, Service.class})}, //注解类型
        @ComponentScan.Filter(type = FilterType.CUSTOM,classes = {MyFilter.class})},//自定义注册类型
               useDefaultFilters = false
)
// 自己定义的过滤条件 需要实现Spring的TypeFilter
public class MyFilter implements TypeFilter {
    /**
     *
     * @param metadataReader 读取到当前正在扫描的类信息
     * @param metadataReaderFactory 可以获取到其他任何类的信息
     * @return
     * @throws IOException
     */
    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        // 获取当前类注解的信息
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        // 获取当前正在扫描类的信息
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        // 获取类路径相关信息
        Resource resource = metadataReader.getResource();
        String className = classMetadata.getClassName();
        System.out.println("->>>"+className);

        return false;
    }
}

(五)给容器中注册组件的方式

  1. 包扫描(@ComponentScan)+组件标注注解(@Controller/@Service/@Repository/@Component)[适用于自己写的类]

  2. @Bean[导入的第三方包组件]

  3. @Import[快速给容器中导入一个组件]

    • @Import (要导入到容器中的组件),容器中就会自动注册这个组件,id默认是组件的全类名。

    • ImportSelector 返回需要导入组件的全类名数组。

    • ImportBeanDefinitionRegistrar 自己注册beanDefinition.

    直接在类上使用该注解,引入需要的组件。

    方式一
    @Import({Color.class, Red.class})
    public class MainConfig2 {
    
    方式二
    @Import({Color.class, Red.class, MyImportSelector.class})
    public class MainConfig2 {
    
    // 自定义逻辑需要导入的组件。
    public class MyImportSelector implements ImportSelector {
        /**
         *
         * @param annotationMetadata 当前标注@Improt注解的类的所有注解信息
         * @return 返回值,就是导入到容器中的组件全类名
         */
        @Override
        public String[] selectImports(AnnotationMetadata annotationMetadata) {
            return new String[]{"com.mt.domain.Blue","com.mt.domain.Yellow"};
        }
    }
    
    方式三
    @Import({Color.class, Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
    public class MainConfig2 {
    
    // 自定义要注册的组件。
    public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
        /**
         *
         * @param importingClassMetadata 当前类的注解信息
         * @param registry BeanDefinitation注册类   所有需要添加到容器中的bean都需要在此注册
         *                 通过registry.registryregisterBeanDefinition手工注册。
         */
        @Override
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    
            RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(RainRow.class);
            registry.registerBeanDefinition("RainRow",rootBeanDefinition);
        }
    }
    
  4. 使用Spring提供的FactoryBean (工厂bean)

    1. 默认获取的是工厂bean提供的getObject()方法创建的对象。
      
    2. 要获取工厂bean本身,我们需要给id前面加一个&。
      
// Spring 提供的FactoryBean(工厂bean)
public class ColorFactory implements FactoryBean<Color>{
    @Override
    public Color getObject() throws Exception {
        return new Color();
    }

    @Override
    public Class<?> getObjectType() {
        return Color.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}
/**
* 注册bean
 */
@Bean
public ColorFactory ColorFactory() {
    return new ColorFactory();
}
@Test
public void test06() {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
    Object colorFactory = applicationContext.getBean("ColorFactory");
    System.out.println(colorFactory);// 返回的是getObject创建的Color对象
    Object colorFactory = applicationContext.getBean("&ColorFactory");
    System.out.println(colorFactory);// 返回的是ColorFactory对象
}

(六)bean的生命周期

实现自定义初始化和销毁:

  1. 指定初始化和销毁方法。
/**
 * @ClassName: MainConfigLifeCycle
 * @Description: bean生命周期的配置
 * @Author: mao-tao
 * @Date: 2020-10-21 18:38
 * @Version: 1.0
 *   容器管理bean的生命周期:   创建  -------- 初始化 ------- 销毁
 *   我们可以自定义初始化和销毁方法。
 *   构造(对象创建):
 *      单实例:在容器启动时创建对象(默认)使用懒加载则与多实例一样。
 *      多实例:在每次调用时创建对象。
 *   初始化:
 *      对象创建好,并赋值好,调用初始化方法。
 *   销毁:
 *       单实例,容器关闭时。
 *       多实例,容器不会管理bean,不会调用销毁方法。
 *    1)、指定初始化和销毁方法
 *          使用@Bean的initMethod和destoryMethod指定。
 **/
@Configuration
public class MainConfigLifeCycle {
    //@Scope(value = "prototype")
    //@Lazy
    @Bean(value = "car",initMethod = "init",destroyMethod = "destroy")
    public Car test01() {
        return new Car();
    }
}
// 自定义初始化和销毁方法
public class Car {
    public Car(){
        System.out.println("car ------ constructor ------");
    }
    public void init() {
        System.out.println("car ------ init ------");
    }
    public void destroy() {
        System.out.println("cr ------ destory ------");
    }
}
  1. 实现接口方式

通过让bean实现InitializingBean(定义初始化逻辑)、DisposableBean(定义销毁逻辑)

public class Cat implements InitializingBean, DisposableBean {
    public Cat() {
        System.out.println("cat ------ contructor ------");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("cat ------ init ------");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("cat ------ destroy ------");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值