Spring 的组件注册注解

注解驱动

目的:
当我们还在使用Spring、SpringMVC、Mybatis三大框架来整合开发的时候,我们会写大量的xml文件来进行配置;然而在Springboot和SpringCloud兴起之后,学习Spring的注解驱动及其原理那将会是非常有必要的了;因为在Springboot和SpringCloud里面会使用到大量的注解来进行配置;当我们熟练掌握了Spring的注解驱动,那当我们在学习Springboot和SpringCloud框架的时候,那将会更加的轻松自如。

@Configuration配置类

// 配置类
@Configuration
public class MainConfig {

    @Bean
    public Person person01() {
        return new Person("1", "wangwu", 12);
    }
}

测试:

public class MyTest {
    @Test
    public void test01() {
        // 使用注解
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
        Person person = (Person) annotationConfigApplicationContext.getBean("person");
        System.out.println(person);
//        String[] beanNamesForType = annotationConfigApplicationContext.getBeanNamesForType(Person.class);
//        for (String beanname : beanNamesForType) {
//            System.out.println(beanname);
//        }

    }
}

@ComponentScan

  • 包扫描注解,会扫描标注了@Controller @Service @Repository @Component注解的类,自动加载到容器中
  • @ComponentScan value:指定要扫描的包
    excludeFilters = Filter[] :指定扫描的时候按照什么规则排除那些组件
    includeFilters = Filter[] :指定扫描的时候只需要包含哪些组件
    FilterType.ANNOTATION:按照注解
    FilterType.ASSIGNABLE_TYPE:按照给定的类型;
    FilterType.ASPECTJ:使用ASPECTJ表达式
    FilterType.REGEX:使用正则指定
    FilterType.CUSTOM:使用自定义规则
// 配置类
@Configuration
// 扫描com.yajun.spring01包下标注了@Controller @Service @Repository @Component注解的类,加载到容器中
@ComponentScan(value = "com.yajun.spring01") 
public class MainConfig {

    @Bean
    public Person person01() {
        return new Person("1", "wangwu", 12);
    }
}

包扫描排除:

解释:包扫描排除按照注解类型排除,排除标注@Controller和@Service注解的类,不加入容器
excludeFilters = Filter[]

@ComponentScan(value = “com.yajun.spring01”, excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class,Service.class})
})

@Scope 设置组件的作用域

prototype:多实例的
singleton:单实例的(默认值)
request:同一次请求创建一个实例(比较少用)
session:同一个session创建一个实例(比较少用)

// 配置类
@Configuration
@ComponentScan(value = "com.yajun.spring01", excludeFilters = {
    @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class, Service.class})
})
public class MainConfig {

    @Bean
    @Scope(value = "prototype")  // 多实例的 调用的时候创建对象
    public Person person() {
        return new Person("1", "wangwu", 12);
    }
}

@Lazy

懒加载:容器启动不创建对象,第一次使用(获取 )的时候创建

@Conditional 按照条件注册bean

按照一定的条件进行判断,满足条件给容器注册bean(可以定义在方法或者类上面)

  • 此注解需要定义一个类实现Condition接口的matches方法,返回boolen类型
public class WindosCondition implements Condition {

    // 判断系统的操作类型
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        BeanDefinitionRegistry registry = conditionContext.getRegistry();
        String[] beanDefinitionNames = registry.getBeanDefinitionNames();
        System.out.println("条件开始执行");
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }

        Environment environment = conditionContext.getEnvironment();
        String property = environment.getProperty("os.name");
        if (property.contains("Windows")) {
            return true;
        }
        return false;
    }
}

配置类:

// 配置类
@Configuration
@ComponentScan(value = "com.yajun.spring01", excludeFilters = {
    @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class, Service.class})
})
public class MainConfig {

    @Bean
//    @Scope(value = "prototype")
//    @Conditional(WindosCondition.class)
    public Person person() {
        return new Person("1", "wangwu", 12);
    }

    @Bean
    @Conditional(WindosCondition.class) // 实现了Contidion接口的类
    public Person person01() {
        return new Person("2", "张三", 14);
    }

    @Bean
    @Conditional(WindosCondition.class)
    public Person person02() {
        return new Person("5", "李四", 15);
    }
}
@Conditional派生注解

在这里插入图片描述

@Improt 快速的给容器中导入一个组件

  • @Import(要导入到容器的组件),容器就会自动注册这个组件,id是默认是 全类名
  • ImportSelector(定义一个类实现ImportSelector): 返回需要导入组件的全类名数组;
  • ImportBeanDefinitionRegistrar(定义一个类实现ImportBeanDefinitionRegistrar):手动注册 bean到容器中

直接导入类:

@Import(Bule.class)
public class MainConfig {

}

导入实现了ImportSelector接口的类,实现方法返回一个类名数组:

public class MyImportSelectot implements ImportSelector {

    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        return new String[]{"com.yajun.spring01.bean.Red","com.yajun.spring01.bean.Yellow"};
    }
}

配置类:

@Import({Bule.class, MyImportSelectot.class})
public class MainConfig {

}

导入实现了ImportBeanDefinitionRegistrar接口的类

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
        BeanDefinition beanDefinition = beanDefinitionRegistry.getBeanDefinition("com.yajun.spring01.bean.Red");
        String beanClassName = beanDefinition.getBeanClassName();
        System.out.println(beanClassName);
        boolean b = beanDefinitionRegistry.containsBeanDefinition("com.yajun.spring01.bean.Red");
        // 如果容器红有Red对象就把Green也注册到容器中
        if (b) {
            BeanDefinition beanDefinition1 = new RootBeanDefinition(Green.class);
            beanDefinitionRegistry.registerBeanDefinition("green",beanDefinition1);
        }
    }
}

配置类

// 用@Import注解把上面的类加载进来
@Import({Bule.class, MyImportSelectot.class, MyImportBeanDefinitionRegistrar.class})
public class MainConfig {
}

@FactoryBean往容器中注册组件

  • 定义一个要创建对象的工厂bean实现FactoryBean。
import org.springframework.beans.factory.FactoryBean;

public class ColorFactoryBean implements FactoryBean<Color> {

    public Color getObject() throws Exception {
        System.out.println("new Color()...");
        return new Color();
    }

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

    public boolean isSingleton() {
        return true;
    }
}
  • 在主配置类中注册创建的工厂bean
 @Bean
    public ColorFactoryBean colorFactoryBean() {
        return new ColorFactoryBean();
    }
}

测试结果:

  
  public class MyTest {
    @Test
    public void test01() {
        // 使用注解
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
        Object colorFactoryBean = annotationConfigApplicationContext.getBean("colorFactoryBean");
        System.out.println(colorFactoryBean.getClass());
     
    }
}

结果:

class com.yajun.spring01.bean.Color

分析:往容器中实际导入的是工厂bean,实际注册的Color对象
如果要拿到ColorFactoryBean本省,获取的时候在名字前面加&符号:

列:Object colorFactoryBean = annotationConfigApplicationContext.getBean("&colorFactoryBean")

给容器注册组件方式:

  1. 包扫描(ComponentScan) + 组件标注注解(@Controller/ @Service/ @Repository/ @Component)【自己写的】

  2. @Bean【导入第三方包里面的组件】

  3. @Import【快速的给容器中导入一个组件】

    1. @Import(要导入到容器的组件),容器就会自动注册这个组件,id是默认是 全类名
    2. ImportSelector(定义一个类实现ImportSelector): 返回需要导入组件的全类名数组;
    3. ImportBeanDefinitionRegistrar(定义一个类实现ImportBeanDefinitionRegistrar):手动注册 bean到容器中
  4. 使用Spring提供的FactoryBean(工厂bean)

bean的生命周期

  • bean的生命周期:
    bean的创建—初始化—销毁的过程
    容器管理bean的生命周期:
    我们可以自定义初始化和销毁方法;容器在bean进行到当前生命周期的时候来调用我们自定义的初始化和销毁方法

指定初始化和销毁方法:指定init-method和destory-method

  1. 指定初始化和销毁的方法:
    通过@Bean指定init-method和destory-method;

bean:

public class Car {

    public void init() {
        System.out.println("Car...init...");
    }

    public void destory() {
        System.out.println("Car...destory...");
    }
}

配置类:

@Configuration
public class MyConfig02 {

    @Bean(initMethod = "init",destroyMethod = "destory")
    public Car car() {
        return new Car();
    }
}

测试:

public class MyTest01 {
    @Test
    public void test01() {
        // 初始化容器
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MyConfig02.class);
        System.out.println("容器启动完成...");
        annotationConfigApplicationContext.close();
    }
}

结果:容器启动的时候,执行了car的init方法,容器关闭的时候执行destory方法

Car...init...
容器启动完成...
Car...destory...
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值