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沒有打印出來。

相關文章
相關標籤/搜索