Spring注册Bean


给容器中注册组件:
1.包扫描+类注解 @Component @Controller @Service @Repository等
2.使用@Bean
3.使用Import
1.直接指定类.class
2.实现ImportSelector接口的子类,会注入返回数组中所有的类
3.实现ImportBeanDefinitionRegistrar接口的子类,其子类方法中包含可以直接注入Bean的对象

注册一个Bean

1.创建一个实体类

 */
public class Person {
    private String name;
    private Integer age;

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

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

2.添加配置类 并直接注入Bean

@Configuration //配置类注解
public class BeanTest {

    public static void main(String [] args){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanTest.class);
        //获取指定类型所有bean的id名列表
        String [] persons = applicationContext.getBeanNamesForType(Person.class);
        //遍历输出名字 (java8)
        Arrays.asList(persons).forEach(System.out::println);
    }
    @Bean //当前方法返回值的对象会注入到spring容器中
    public Person person(){
        return new Person("张三",18);
    }
    @Bean //bean的id默认是方法名
    public Person person1(){
        return new Person("李四",20);
    }
    @Bean("wangwu") //当然也可以直接指定id名
    public Person person2(){
        return new Person("王五",14);
    }
}

2.2.1 扫描指定包内的Bean

@Controller
public class BookController {
}

@Service
public class BookService {
}

@Repository
public class BookDao {
}

@Configuration
//扫描指定的包
@ComponentScan(value = "com.lx.springannotation")
public class TestBean {
    public static void main(String [] args){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(TestBean.class);
        //获取容器中所有bean
        String[] names = applicationContext.getBeanDefinitionNames();
        Arrays.asList(names).forEach(System.out::println);
    }
}

2.2.2 扫描指定包内的Bean 并过滤

//1.去掉指定注解类型的Bean
@Configuration
//扫描指定的包
@ComponentScan(value = "com.lx.spring_annotation"
        //去掉指定类型的Bean
        ,excludeFilters = {
            @ComponentScan.Filter(
                    //指定需要过滤的类型(ANNOTATION,ASSIGNABLE_TYPE,ASPECTJ,REGEX,CUSTOM)
                    type = FilterType.ANNOTATION,
                    value = {Controller.class, Service.class}
            )
        }
)
public class TestBean {
    public static void main(String [] args){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(TestBean.class);
        //获取容器中所有bean
        String[] names = applicationContext.getBeanDefinitionNames();
        Arrays.asList(names).forEach(System.out::println);
    }
}



2.2.3只获取指定注解类型的Bean

@Configuration
//扫描指定的包
@ComponentScan(value = "com.lx.spring_annotation"
        ,includeFilters = {
        @ComponentScan.Filter(
                //指定需要过滤的类型(ANNOTATION,ASSIGNABLE_TYPE,ASPECTJ,REGEX,CUSTOM)
                type = FilterType.ANNOTATION,
                value = {Controller.class, Service.class}
        )
        }
//        当需要使用includeFilters需要将 useDefaultFilters置为false ,否则includeFilters不起作用
        ,useDefaultFilters = false
)
public class TestBean {
    public static void main(String [] args){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(TestBean.class);
        //获取容器中所有bean
        String[] names = applicationContext.getBeanDefinitionNames();
        Arrays.asList(names).forEach(System.out::println);
    }
}

2.2.4只获取指定类型的Bean

@Configuration
@ComponentScan(value = "com.lx.spring_annotation"
        ,includeFilters = {
        	//ASSIGNABLE_TYPE:指定类的类型 只获取BookService类型的类
			@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,value = {BookService.class})
			//ANNOTATION:注解的类型
			,@ComponentScan.Filter(type = FilterType.ANNOTATION,value = {Controller.class})
        }
        ,useDefaultFilters = false
)
public class TestBean {
    public static void main(String [] args){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(TestBean.class);
        //获取容器中所有bean
        String[] names = applicationContext.getBeanDefinitionNames();
        Arrays.asList(names).forEach(System.out::println);
    }
}

2.2.5.获取自定义过滤规则

//自定义过滤规则
class MyTypeFilter implements TypeFilter {
    //MetadataReader:当前扫描类的的信息
    //MetadataReaderFactory:可以获取到其他任何类的信息
    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        //获取当前扫描类的注解信息
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        //获取当前类的加载信息
        Resource resource = metadataReader.getResource();
        //获取当前扫描类的类信息
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        System.out.println(classMetadata.getClassName());
        //例如类名包含"er"
        return classMetadata.getClassName().contains("er");
    }
}

@Configuration
//扫描指定的包
@ComponentScan(value = "com.lx.spring_annotation.bean02"
        ,includeFilters = {
            //CUSTOM:用户自定义类型
            @ComponentScan.Filter(type = FilterType.CUSTOM,value = {MyTypeFilter.class})
        }
        ,useDefaultFilters = false
)
public class TestBean {
    public static void main(String [] args){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(TestBean.class);
        //获取容器中所有bean
        String[] names = applicationContext.getBeanDefinitionNames();
        Arrays.asList(names).forEach(System.out::println);
    }
}


3.1 对象的作用域及懒加载

@Configuration
public class BeanTest01 {

    public static void main(String [] args){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanTest01.class);
        System.out.println("初始化结束!");
        Person p1 = applicationContext.getBean("zhangsan",Person.class);
        Person p2 = applicationContext.getBean("zhangsan",Person.class);
        System.out.println(p1 == p2);//单例时每次获取的对象相同,在初始化时就创建对象
        Person p3 = applicationContext.getBean("lisi",Person.class);
        Person p4 = applicationContext.getBean("lisi",Person.class);
        System.out.println(p3 == p4);//多例时每次获取对象不同,并且只有在获取对象时,才调用创建方法

        System.out.println("第一次获取王五");//初始化不会创建对象
        Person p5 = applicationContext.getBean("wangwu",Person.class);
    }

    //默认是单例的
//    @Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
    @Bean("zhangsan")
    public Person person(){
        //当作用域为singletion 时,初始化时就会创建对象,每次获取对象是同一个
        System.out.println("开始创建对象:张三");
        return new Person("张三",12);
    }

    //取值为prototype时为多例
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    @Bean("lisi")
    public Person person1(){
        //当作用域为prototype时,在从ioc容器中获取对象时才会创建,每次获取对象都会新建
        System.out.println("开始创建对象:李四");
        return new Person("李四",13);
    }

    //延迟加载
    @Lazy
    @Bean("wangwu")
    public Person person2(){
        //初始化不会调用次方法
        System.out.println("开始创建对象:王五");
        return new Person("王五",12);
    }
}

4.给定条件创建对象(springboot底层大量使用)

@Configuration
public class BeanTest02 {

    public static void main(String [] args){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanTest02.class);
        ConfigurableEnvironment environment = applicationContext.getEnvironment();//获取系统变量
        System.out.println(environment.getProperty("os.name"));//获取系统名
        Map<String, Person> beansOfType = applicationContext.getBeansOfType(Person.class);//获取所有的Person
        System.out.println(beansOfType);
    }

    //判断当前Bean是否需要添加到容器中,需要传入Condition的子类
    @Conditional({LinuxCondition.class})
    @Bean
    public Person linux(){
        return new Person("linux",100);
    }

    @Conditional({WindowsCondition.class})
    @Bean
    public Person windows(){
        return new Person("windows",100);
    }

}
class LinuxCondition implements Condition {
    //context :获取当前上下文信息
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Environment environment = context.getEnvironment();//获取环境变量
        return environment.getProperty("os.name").toLowerCase().contains("linux");
    }

}
class WindowsCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Environment environment = context.getEnvironment();//获取环境变量
        return environment.getProperty("os.name").toLowerCase().contains("windows");
    }

}

使用@Import导入类(可以是)到容器中

import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.*;
import org.springframework.core.type.AnnotationMetadata;

import java.awt.print.Book;
import java.sql.Time;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Scanner;
import java.util.zip.ZipEntry;

/**
 * 创建人:游林夕/2019/7/13 20 12
 */
@Configuration
//加载类到ioc容器中,id是类的全限定名
//如果类是ImportSelector的子类,就会加载selectImports方法返回的类数组
//如果类是ImportBeanDefinitionRegistrar的子类,在registerBeanDefinitions方法中就可以直接注册Bean
@Import({Date.class,ImportSelectorImpl.class,ImportBeanDefinitionRegistrarImpl.class})
public class BeanTest03 {
    public static void main(String [] args){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanTest03.class);
        String[] names = applicationContext.getBeanDefinitionNames();
        Arrays.asList(names).forEach(System.out::println);
    }
}
class ImportSelectorImpl implements ImportSelector{
    @Override
    //AnnotationMetadata对象可以获取到调用此方法的类所有注解的信息
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"java.awt.print.Book"};
    }
}
class ImportBeanDefinitionRegistrarImpl implements ImportBeanDefinitionRegistrar{

    @Override
    //AnnotationMetadata对象可以获取到调用此方法的类所有注解的信息
    //BeanDefinitionRegistry:可以获取到Bean定义的对象,可以自己添加Bean,删除Bean
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        boolean b = registry.containsBeanDefinition("java.util.Date");//判断容器中是否有Date
        boolean b1 = registry.containsBeanDefinition("java.awt.print.Book");
        if (b && b1){
            //Bean的注册信息
            RootBeanDefinition definition = new RootBeanDefinition(ArrayList.class);
            registry.registerBeanDefinition("list",definition);
        }
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值