组件注册

组件注册实现方式

     给容器中注册组件;
     1)、包扫描+组件标注注解(@Controller/@Service/@Repository/@Component)[自己写的类]
     2)、@Bean[导入的第三方包里面的组件]
     3)、@Import[快速给容器中导入一个组件]
       3.1)、@Import(要导入到容器中的组件);容器中就会自动注册这个组件,id默认是全类名
       3.2)、ImportSelector:返回需要导入的组件的全类名数组;
       3.3)、ImportBeanDefinitionRegistrar:手动注册bean到容器中
     4)、使用Spring提供的 FactoryBean(工厂Bean);
       4.1)、默认获取到的是工厂bean调用getObject创建的对象
       4.2)、要获取工厂Bean本身,我们需要给id前面加一个&&colorFactoryBean)

1.@Configuration+@Bean给容器当中注册组件

代码实现

@ C o n f i g u r a t i o n : 告 诉 S p r i n g 这 是 一 个 配 置 类 \color{blue}{@Configuration:告诉Spring这是一个配置类} @ConfigurationSpring

@Configuration
public class MainConfig {
    /**
     * 给容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id
     */
    @Bean("person")
    public Person person() {
        return new Person("ly", 27);
    }
}
@Data
public class Person {
    @Value("ly")
    private String name;
    @Value("#{20-2}")
    private Integer age;
    @Value("${person.nickName}")
    private String nickName;

    public Person(String name, Integer age) {
        super();
        this.name = name;
        this.age = age;
    }

    public Person() {
        super();
    }
}

测 试 \color{red}{测试}

public class MainTest {
    public static void main(String[] args) {
        //注解的方式创建一个bean
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
        Person person = (Person) applicationContext.getBean("person");
        System.out.println(person);

        String[] namesForType = applicationContext.getBeanNamesForType(Person.class);
        Arrays.stream(namesForType).forEach(System.out::println);
    }
}

2.@ComponentScan自动扫描组件

代码实现

@Controller
public class BookController {
}
@Service
public class BookService {
}
@Repository
public class BookDao {
}
@Configuration
@ComponentScan(value = "com.ly.springannotation")
public class MainConfig {
}
    /**
     * @param
     * @return void
     * @Description: 获取容器当中所有定义bean的名字
     * 测试@ComponentScan 包扫描
     * @author luoyong
     * @create 21:44 2019/12/28
     * @last modify by [LuoYong 21:44 2019/12/28 ]
     */
    @Test
    public void test1() {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        //获取容器当中所有定义bean的名字
        Arrays.stream(beanDefinitionNames).forEach(System.out::println);
    }

excludeFilters()&&includeFilters()

e x c l u d e F i l t e r s ( ) : 指 定 扫 描 的 时 候 按 照 什 么 规 则 排 除 那 些 组 件 \color{blue}{excludeFilters() :指定扫描的时候按照什么规则排除那些组件} excludeFilters()
i n c l u d e F i l t e r s ( ) : 指 定 扫 描 的 时 候 需 要 包 含 那 些 组 件 默 认 按 照 默 认 的 过 滤 器 扫 描 所 有 这 边 设 置 u s e D e f a u l t F i l t e r s = f a l s e \color{blue}{includeFilters() :指定扫描的时候需要包含那些组件 默认按照默认的过滤器 扫描所有 这边设置 useDefaultFilters = false} includeFilters()useDefaultFilters=false

FilterType.ANNOTATION:按照注解
FilterType.ASSIGNABLE_TYPE:按照给定的类型}
FilterType.ASPECTJ:使用ASPECTJ表达式
FilterType.REGEX:使用正则指定
FilterType.CUSTOM:使用自定义规则

按照注解排除某些组件
@Configuration
@ComponentScan(value = "com.ly.springannotation", excludeFilters = {
        @Filter(type = FilterType.ANNOTATION, classes = {Controller.class, Service.class}),
        @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {Person.class})
})
public class MainConfig {
}
只注册某些组件

u s e D e f a u l t F i l t e r s 默 认 值 为 t r u e 扫 描 所 有 所 以 要 将 该 值 设 置 为 f a l s e \color{blue}{useDefaultFilters 默认值为true 扫描所有 所以要将该值设置为false} useDefaultFilterstruefalse

@Configuration
@ComponentScan(value = "com.ly.springannotation", includeFilters = {
//        @Filter(type = FilterType.ANNOTATION, classes = {Controller.class}),
//        @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {Person.class}),
        @Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class}),
}, useDefaultFilters = false)
public class MainConfig {

    /**
     * 给容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id
     */
    @Bean("person")
    public Person person() {
        return new Person("ly", 27);
    }
}
/**
 * @author luoyong
 * @Description: MyTypeFilter
 * 自定义类型过滤器
 * @create 2019-12-28 22:04
 * @last modify by [LuoYong 2019-12-28 22:04]
 **/
public class MyTypeFilter implements TypeFilter {

    /**
     * @param metadataReader        读取到的当前正在扫描类的信息
     * @param metadataReaderFactory 可以获取到其他任何类的信息
     * @return boolean
     * @Description:
     * @author luoyong
     * @create 22:05 2019/12/28
     * @last modify by [LuoYong 22:05 2019/12/28 ]
     */
    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        //1:获取当前类的注解信息
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        //2:获取当前正在扫描类的信息
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        //获取当前类资源(类的路径)
        Resource resource = metadataReader.getResource();

        String className = classMetadata.getClassName();
        System.out.println("---->" + className);
        if (className.contains("ers")) {
            //过滤规则
            return true;
        }
        return false;
    }
}

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

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

代码实现
package com.ly.springannotation.config;
/**
 * @author luoyong
 * @Description: MainConfig2
 * @create 2019-12-28 22:38
 * @last modify by [LuoYong 2019-12-28 22:38]
 **/
@Conditional({LinuxCondition.class})
@Configuration
//@Import导入组件,id默认是组件的全类名
@Import({Color.class, Red.class})
public class MainConfig2 {
    @Bean
    public Person person() {
        System.out.println("往容器当中添加Person....");
        return new Person("张三", 25);
    }
    /**
     * @Conditional({Condition}) : 按照一定的条件进行判断,满足条件给容器中注册bean
     * <p>
     * 如果系统是windows,给容器中注册("bill")
     * 如果是linux系统,给容器中注册("linus")
     */
    @Conditional(WindowsCondition.class)
    @Bean("bill")
    public Person person01() {
        return new Person("Bill Gates", 62);
    }

    @Conditional(LinuxCondition.class)
    @Bean("linus")
    public Person person02() {
        return new Person("linus", 66);
    }
}
public class Color {}
public class Red {
}

测试

    /**
     * @param
     * @return void
     * @Description: 测试给容器当中导入组件
     * @author luoyong
     * @create 9:48 2019/12/29
     * @last modify by [LuoYong 9:48 2019/12/29 ]
     */
    @Test
    public void testImport() {
        //打印当前容器当中注册的bean
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        Arrays.stream(beanDefinitionNames).forEach(System.out::println);
    }

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

代码实现
package com.ly.springannotation.config;
/**
 * @author luoyong
 * @Description: MainConfig2
 * @create 2019-12-28 22:38
 * @last modify by [LuoYong 2019-12-28 22:38]
 **/
@Conditional({LinuxCondition.class})
@Configuration
//@Import导入组件,id默认是组件的全类名
@Import({Color.class, Red.class,MyImportSelector.class})
public class MainConfig2 {
    @Bean
    public Person person() {
        System.out.println("往容器当中添加Person....");
        return new Person("张三", 25);
    }
    /**
     * @Conditional({Condition}) : 按照一定的条件进行判断,满足条件给容器中注册bean
     * <p>
     * 如果系统是windows,给容器中注册("bill")
     * 如果是linux系统,给容器中注册("linus")
     */
    @Conditional(WindowsCondition.class)
    @Bean("bill")
    public Person person01() {
        return new Person("Bill Gates", 62);
    }

    @Conditional(LinuxCondition.class)
    @Bean("linus")
    public Person person02() {
        return new Person("linus", 66);
    }
}
public class MyImportSelector implements ImportSelector {
    /**
     * @param importingClassMetadata 当前标注@Import注解的类的所有注解信息
     * @return
     * @Description: 返回值:就是要导入到容器中的组件全类名
     * @author luoyong
     * @create 10:20 2019/12/29
     * @last modify by [LuoYong 10:20 2019/12/29 ]
     */
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        //方法的返回值不能为空 否则会报空指针异常
        return new String[]{"com.ly.springannotation.bean.Blue", "com.ly.springannotation.bean.Yellow"};
    }
}
public class Blue {
}
public class Yellow {
}

测试

    @Test
    public void testImport() {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
        //打印当前容器当中注册的bean
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        Arrays.stream(beanDefinitionNames).forEach(System.out::println);

        Blue blue = (Blue) applicationContext.getBean(Blue.class);
        System.out.println(blue);
    }

ImportBeanDefinitionRegistrar:手动注册bean到容器

代码实现
/**
 * @author luoyong
 * @Description: MainConfig2
 * @create 2019-12-28 22:38
 * @last modify by [LuoYong 2019-12-28 22:38]
 **/
@Conditional({LinuxCondition.class})
@Configuration
//@Import导入组件,id默认是组件的全类名
@Import({Color.class, Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class MainConfig2 {
    @Bean
    public Person person() {
        System.out.println("往容器当中添加Person....");
        return new Person("张三", 25);
    }
    /**
     * @Conditional({Condition}) : 按照一定的条件进行判断,满足条件给容器中注册bean
     * <p>
     * 如果系统是windows,给容器中注册("bill")
     * 如果是linux系统,给容器中注册("linus")
     */
    @Conditional(WindowsCondition.class)
    @Bean("bill")
    public Person person01() {
        return new Person("Bill Gates", 62);
    }
    @Conditional(LinuxCondition.class)
    @Bean("linus")
    public Person person02() {
        return new Person("linus", 66);
    }
}
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    /**
     * @param importingClassMetadata 当前类的注解信息
     * @param registry               BeanDefinition注册类
     * @return void
     * @Description: 把所有需要添加到容器当中bean:调用BeanDefinitionRegistry.registerBeanDefinition手工注册进来
     * @author luoyong
     * @create 10:36 2019/12/29
     * @last modify by [LuoYong 10:36 2019/12/29 ]
     */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        boolean blueBean = registry.containsBeanDefinition("com.ly.springannotation.bean.Blue");
        boolean yellowBean = registry.containsBeanDefinition("com.ly.springannotation.bean.Yellow");
        if (blueBean && yellowBean) {
            //指定bean的定义信息
            RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(RainBow.class);
            //注册一个bean 并指定bean名
            registry.registerBeanDefinition("rainBow", rootBeanDefinition);
        }
    }
}
public class RainBow {
}

4.FactoryBean Spring提供的工厂bean

代码实现

/**
 * @author luoyong
 * @Description: 创建一个Spring定义的FactoryBean
 * @create 2019-12-29 10:49
 * @last modify by [LuoYong 2019-12-29 10:49]
 **/
public class ColorFactoryBean implements FactoryBean<Color> {

    /**
     * @param
     * @return
     * @Description: 返回一个Color对象,这个对象会添加到容器中
     * @author luoyong
     * @create 10:52 2019/12/29
     * @last modify by [LuoYong 10:52 2019/12/29 ]
     */
    @Override
    public Color getObject() throws Exception {
        System.out.println("ColorFactoryBean...getObject...");
        return new Color();
    }

    @Override
    public Class<?> getObjectType() {
        return Color.class;
    }
    /**
     * @param
     * @return boolean
     * @Description: 是否是单例的
     * true:bean是单例的 在容器中保存一份
     * false:多实例,每次获取都会创建一个新的bean
     * @author luoyong
     * @create 10:50 2019/12/29
     * @last modify by [LuoYong 10:50 2019/12/29 ]
     */
    @Override
    public boolean isSingleton() {
        return true;
    }
}
public class Color {
}
/**
 * @author luoyong
 * @Description: MainConfig2
 * @create 2019-12-28 22:38
 * @last modify by [LuoYong 2019-12-28 22:38]
 **/
@Conditional({LinuxCondition.class})
@Configuration
//@Import导入组件,id默认是组件的全类名
@Import({Color.class, Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class MainConfig2 {
    @Bean
    public Person person() {
        System.out.println("往容器当中添加Person....");
        return new Person("张三", 25);
    }
    /**
     * @Conditional({Condition}) : 按照一定的条件进行判断,满足条件给容器中注册bean
     * <p>
     * 如果系统是windows,给容器中注册("bill")
     * 如果是linux系统,给容器中注册("linus")
     */
    @Conditional(WindowsCondition.class)
    @Bean("bill")
    public Person person01() {
        return new Person("Bill Gates", 62);
    }

    @Conditional(LinuxCondition.class)
    @Bean("linus")
    public Person person02() {
        return new Person("linus", 66);
    }

    /**
     * 使用Spring提供的 FactoryBean(工厂Bean)
     * 1)、默认获取到的是工厂bean调用getObject创建的对象
     * 2)、要获取工厂Bean本身,我们需要给id前面加一个&&colorFactoryBean)
     *                
     */
    @Bean
    public ColorFactoryBean colorFactoryBean() {
        return new ColorFactoryBean();
    }
}

测试

    /**
     * @param
     * @return void
     * @Description: 测试FactoryBean注册bean
     * @author luoyong
     * @create 9:48 2019/12/29
     * @last modify by [LuoYong 9:48 2019/12/29 ]
     */
    @Test
    public void testFactoryBean() {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
        System.out.println("FactoryBean...");
        Object bean = applicationContext.getBean("colorFactoryBean");
        Object bean2 = applicationContext.getBean("colorFactoryBean");
        System.out.println("bean的类型:" + bean.getClass());
        System.out.println(bean == bean2);

        //获取bean工厂本身
        Object bean4 = applicationContext.getBean("&colorFactoryBean");
        System.out.println(bean4.getClass());
    }

在这里插入图片描述

其他

设置组件的作用域和懒加载

@Configuration
public class MainConfig2 {
    /**
     * @param
     * @return
     * @Description: @Scope 作用域
     * prototype:多实例的:ioc容器启动并不会去调用方法创建对象放在容器中。每次获取的时候才会调用方法创建对象;
     * singleton:单实例的(默认值):ioc容器启动会调用方法创建对象放到ioc容器中。以后每次获取就是直接从容器(map.get())中拿,
     * request:同一次请求创建一个实例
     * session:同一个session创建一个实例
     * @author luoyong
     * @create 22:48 2019/12/28
     * @last modify by [LuoYong 22:48 2019/12/28 ]
     */
    @Bean
//    @Scope("prototype")
    @Scope
    /**
     * 懒加载:针对于单实例bean
     * 单实例bean:默认在容器启动的时候创建对象
     * 懒加载:容器启动之后不创建对象,第一使用(获取时)Bean时才去创建对象,并进行初始化
     */
//    @Lazy
    public Person person() {
        System.out.println("往容器当中添加Person....");
        return new Person("张三", 25);
    }
    /**
     * @param
     * @return void
     * @Description: 测试@Scope和@Lazy
     * @author luoyong
     * @create 23:03 2019/12/28
     * @last modify by [LuoYong 23:03 2019/12/28 ]
     */
    @Test
    public void test2() {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        //获取容器当中所有定义bean的名字
        Arrays.stream(beanDefinitionNames).forEach(System.out::println);
        System.out.println("IOC容器创建完成");
        //默认作用域是单例的
        Person person = (Person) applicationContext.getBean("person");
        System.out.println(person);
        Person person2 = (Person) applicationContext.getBean("person");
        System.out.println(person2);
        System.out.println(person == person2);
    }

@Conditional根据条件注册bean

代码实现

/**
 * @author luoyong
 * @Description: MainConfig2
 * @create 2019-12-28 22:38
 * @last modify by [LuoYong 2019-12-28 22:38]
 **/
@Conditional({LinuxCondition.class})
@Configuration
public class MainConfig2 {
    /**
     * @Conditional({Condition}) : 按照一定的条件进行判断,满足条件给容器中注册bean
     * <p>
     * 如果系统是windows,给容器中注册("bill")
     * 如果是linux系统,给容器中注册("linus")
     */
    @Conditional(WindowsCondition.class)
    @Bean("bill")
    public Person person01() {
        return new Person("Bill Gates", 62);
    }

    @Conditional(LinuxCondition.class)
    @Bean("linus")
    public Person person02() {
        return new Person("linus", 66);
    }
}
public class LinuxCondition implements Condition {
    /**
     * @param context  判断条件能使用的上下文
     * @param metadata 注释信息
     * @return boolean
     * @Description: 是否linux系统
     * @author luoyong
     * @create 23:14 2019/12/28
     * @last modify by [LuoYong 23:14 2019/12/28 ]
     */
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        //1:能获取到ioc使用的beanFactory
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        //2:获取类的加载器
        ClassLoader classLoader = context.getClassLoader();
        //3:获取当前环境
        Environment environment = context.getEnvironment();
        //4:获取到bean定义的注册类
        BeanDefinitionRegistry registry = context.getRegistry();
        String property = environment.getProperty("os.name");
        //可以判断容器当中bean注册的情况 也可以给容器当中注册bean
        boolean definition = registry.containsBeanDefinition("person");
        if (property.contains("linux")|| property.contains("Mac")){
            return true;
        }
        return false;
    }
}
public class WindowsCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Environment environment = context.getEnvironment();
        String property = environment.getProperty("os.name");
        if (property.contains("Windows")) {
            return true;
        }
        return false;
    }

}
    /**
     * @param
     * @return void
     * @Description: @Conditional 根据条件注册bean
     * @author luoyong
     * @create 23:07 2019/12/28
     * @last modify by [LuoYong 23:07 2019/12/28 ]
     */
    @Test
    public void test3() {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
        //动态获取环境变量的值:Mac OS X
        Environment environment = applicationContext.getEnvironment();
        String property = environment.getProperty("os.name");
        System.out.println("当前环境是:" + property);
        System.out.println(environment.getActiveProfiles());

        String[] beanNamesForType = applicationContext.getBeanNamesForType(Person.class);
        Arrays.stream(beanNamesForType).forEach(System.out::println);

        //获取Person.class 类型的所有bean的信息
        Map<String, Person> beansOfType = applicationContext.getBeansOfType(Person.class);
        System.out.println(beansOfType);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值