spring 配置bean注入到ioc容器的各种方式

 

第一种:xml配置bean,beans.xml中的一个bean

 

 <bean id="persion" class="com.thl.bean.Persion">
        <property name="uid" value="1"></property>
        <property name="name" value="1900614@qq.com"></property>
        <property name="pwd" value="123456"></property>
    </bean>
property对应pojo,这种是通过Get和Set方法注入到bean中的
测试: 
 @Test
    public void beanTestXml() {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        Persion persion = (Persion) context.getBean("persion");
        System.out.println(persion);
    }

第二种:扫描的方式 ComponentScan

会装配标识了@Controller,@Service,@Repository,@Component注解的类到spring容器中

实际上是他们中有一个共同注解@Component

beans中配置

 <context:component-scan base-package="com.thl.service">

或者通过  @ComponentScan注解

并且可以自定义扫描方式,自定义需要实现TypeFilter 接口

举例:

// excludeFilters 排除那些组件
// includeFilters 只包含哪些组件 但是要配置 useDefaultFilters = false
//
/**
 * ANNOTATION:指定类
 * ASSIGNABLE_TYPE:指定类型
 * ASPECTJ:ASPECTJ表达式
 * REGEX:正则表达式
 * CUSTOM:自定义规则 需要实现TypeFilter
 */
// jdk8 @ComponentScan可以多写几次 指定扫描策略
@ComponentScan(value = "com.thl", includeFilters = {//按照注解排除 加了 Repository注解的
      //  @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Repository.class}),
        //ASSIGNABLE_TYPE 指定类型 Persion以及子类 包含进来
      //  @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {Persion.class})

        @ComponentScan.Filter(type = FilterType.CUSTOM,classes = {MyScanFilter.class})
}, useDefaultFilters = false)
public class ComponentScanCofig {
}


public class MyScanFilter implements TypeFilter {
    /**
     * @param metadataReader        读取到当前正在扫描类的信息
     * @param metadataReaderFactory 读取到其他任何类的信息
     * @return
     * @throws IOException
     */
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        //获取当前类的注解的信息
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        //获取当前类的类信息
        ClassMetadata classMetadata = metadataReader.getClassMetadata();

        String className = classMetadata.getClassName();//拿到类名
        System.out.println("自定义扫描的类" + className);
        if (className.toLowerCase().contains("dao")) {//如果包含dao关键字
            return true;
        }

        //获取当前类的路径
        Resource resource = metadataReader.getResource();


        return false;
    }
}


  /**
     * 测试 ComponetScan 扫描
     */
    @Test
    public void iocTest() {

        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ComponentScanCofig.class);
        //获取扫描所有的bean
        String[] beanDefinitionNames = context.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }
    }

第三种:@Bean 配置类获取bean

并且可以懒加载@Lazy和多种作用域@Scop

/**  @Scope()
 * singleton 表示在spring容器中的单例,通过spring容器获得该bean时总是返回唯一的实例 spring启动的时候启动
 * prototype表示每次获得bean都会生成一个新的对象 启动的时候不会启动 调用的时候创建
 * request表示在一次http请求内有效(只适用于web应用)
 * session表示在一个用户会话内有效(只适用于web应用)
 */

**
     * 懒加载  spring启动不加载 第一次获取的时候加载
     */

@Configuration
public class Beans {
@Lazy
@Scope(value = "prototype")
@Bean("P1")
    public Persion persionRoot() {
        return new Persion(1, "root", "123456");
    }
}

第四种:@Import注入bean

@Import接收一个数组,放入其中即可加入到IOC容器中

 

@Import({A.class,B.class})
public class Beans{}

并且可以通过实现ImportSelector收集需要导入多个配置类 实现ImportBeanDefinitionRegistrar 动态注入bean

举例:

@Configuration
@Import({MyImportSelect.class,MyImportBeanDefinitionRegistrar.class})//快速导入组件,名字为全类名 容器就会注册这个组件
public class Beans {


}

public class MyImportSelect implements ImportSelector {
    //标注 @import的所有类名
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        //返回值为导入到容器的所有全类名 可以返回空数组 但是不要返回null
//        System.out.println(Bule.class.getName());
        return new String[]{Bule.class.getName(), Green.class.getName()};
    }
}

class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    //AnnotationMetadata 当前类的注解信息
    //BeanDefinitionRegistry  BeanDefinition注册类
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        boolean red = registry.containsBeanDefinition("red");//是否有红色
        if(!red){
            RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Red.class);
            registry.registerBeanDefinition("red",rootBeanDefinition );
        }
    }
}

第五种:@Conditional满足条件创建Bean

@Configuration
//@Conditional({LinuxCondition.class})//放在类上 满足当前条件 这个类中配置的所有bean才会生效 统一设置
public class Beans {
@Bean("WinP1")
    @Conditional({WinCondition.class})
    public Persion WinP1() {
        return new Persion(1, "user", "123456");
    }
    @Bean("LinuxP1")
    @Conditional({LinuxCondition.class})
    public Persion LinuxP1() {
        return new Persion(1, "root", "123456");
    }

    @Bean
    public MyFactoryBean myFactoryBean(){
        return  new MyFactoryBean();
    }

}

/**
     *
     * @param context  判断上下文使用的环境
     * @param metadata 标注了当前Condition的注释信息
     * @return
     */
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        //IOC的beanFactory
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        //类加载器
        ClassLoader classLoader = context.getClassLoader();
        //当前环境信息
        Environment environment = context.getEnvironment();
        //bean的注册定义
        BeanDefinitionRegistry registry = context.getRegistry();

        String property = environment.getProperty("os.name");
        if(property.contains("Windows")){
            return true;
        }
        return false;
    }
//LinuxCondition也是一样

第六种:通过BeanFactory创建

需要实现FactoryBean接口

public class MyFactoryBean implements FactoryBean<Red> {
    public Red getObject() throws Exception {
        //调用 getObject创建的对象
        System.out.println("getObject的到 red bean");
        return new Red();
    }

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

    public boolean isSingleton() {
        return true;
    }
}


@Configuration
public class Beans {
 @Bean
    public MyFactoryBean myFactoryBean(){
        return  new MyFactoryBean();
    }
}

@Test
    public void beans() {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Beans.class);
        String[] beanDefinitionNames = context.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }

        // name 前面加上& 获取bean本身 直接写name获取工厂返回的bean
        Object myFactoryBean = context.getBean("myFactoryBean");
        System.out.println(myFactoryBean);

    }

 


版权声明:本文为qq_40859018原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。