spring学习之bean的定义

除了@Bean定义bean之外,spring还提供了其余的定义形式。spring

@Component、@Repository、@Service、@Controller和@Configuration

@Component是spring定义bean的通用注解,@Repository、@Service和@Controller等注解,都是继承@Component。
@Repository用于持久层,@Service用于服务层,@Controller用于控制层。
若是仅仅只是为了定义bean,随便用哪一个均可以,可是为了的区分用于哪一个场景,以及将来spring的扩展,仍是用对应场景的注解。
@Configuration主要场景是看成配置文件,引入bean,好比以前的测试代码,都是用@Configuration来作配置文件。
默认是第一个小写的class名,若是想自定义,能够在括号后面定义本身想要的名称,好比@Service("abc")
MyConfig,ComponentScan注解后面讲,就是扫描包的路径。app

@Configuration
@ComponentScan(value="com.learn.annotation")
public class MyConfig {

}

MyComponentide

@Component
public class MyComponent {
}

其余注解雷同,这边不作重复。
测试代码:测试

@Test
public void test(){
    ApplicationContext app =  new AnnotationConfigApplicationContext(MyConfig.class);
    System.out.println(app.getBean("myConfig"));
    System.out.println(app.getBean("myDao"));
    System.out.println(app.getBean("myComponent"));
    System.out.println(app.getBean("myService"));
    System.out.println(app.getBean("myController"));
}

运行结果:
image.pngspa

@import

在XML配置文件中,用的是<import>标签,在注解中,用@import注解。能够import普通bean,也能够引入配置bean。
这种方法简化了容器实例化,由于只须要处理一个类,而不须要在构造期间记住大量的@Configuration类。
MyConfigcode

@Configuration
@Import({MyComponent.class,MyService.class,MyDao.class,MyController.class})
public class MyConfig {

}

测试方法:blog

@Test
public void test(){
    ApplicationContext app =  new AnnotationConfigApplicationContext(MyConfig.class);
    String[] names = app.getBeanDefinitionNames();
    for (String name : names) {
        System.out.println(name);
    }
}

运行结果:
image.png
虽然AnnotationConfigApplicationContext只引入了MyConfig.class,可是MyConfig中import了多个类,因此都打印了出来。与@Bean不一样的是,bean的id是全类名。继承

ImportSelector

除了@import注解,也能够经过实现ImportSelector接口来引入类。
MyConfig接口

@Configuration
@Import(MyImportSelector.class)
public class MyConfig {

}

MyImportSelectorget

public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        return new String[]{"com.learn.annotation.MyComponent","com.learn.annotation.MyService"};
    }
}
@Test
public void test(){
    ApplicationContext app =  new AnnotationConfigApplicationContext(MyConfig.class);
    String[] names = app.getBeanDefinitionNames();
    for (String name : names) {
        System.out.println(name);
    }
}

运行结果以下:
image.png
注意的是,MyImportSelector并无在容器中。

@Conditional

当咱们根据不一样的场景,好比是否实例化一个bean、根据不一样环境变量实例化某些不一样参数的bean等,咱们能够用@Conditional这个注解。
下面模拟一个简单的例子,若是bean的名称是one就实例化,除非不实例化。
MyConditional

public class MyConditional implements Condition {
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        StandardMethodMetadata standardMethodMetadata = ((StandardMethodMetadata) annotatedTypeMetadata);
        return standardMethodMetadata.getMethodName().equals("one");
    }
}

MyConfig

@Configuration
public class MyConfig {
    @Bean()
    @Conditional(MyConditional.class)
    public One one(){
        return new One();
    }

    @Bean()
    @Conditional(MyConditional.class)
    public Two two(){
        return new Two();
    }
}

测试代码

@Test
public void test(){
    ApplicationContext app =  new AnnotationConfigApplicationContext(MyConfig.class);
    String[] names = app.getBeanDefinitionNames();
    for (String name : names) {
        System.out.println(name);
    }
}

运行结果以下:
image.png能够看出,two这个bean没有打印出来。

相关文章
相关标签/搜索