Spring(二):Bean的裝配

講解bean的裝配

自動化裝配

註解配置

當使用@Configutation註解的類,則聲明該類爲一個配置類,與配置類有關的註解還有:

  • @ComponentScan
  • @ComponentScans

它們都是用來指定包掃描路徑的,使用方法如下:

@Configuration
@ComponentScan("wang.ismy.spring")
public class Config {}

裝配Bean

@Component // 將當前類對象放入容器
public class Bean {...}

@Component這個註解修飾的類,如果類路徑在容器的掃描路徑中(兄弟包以及子包),則該類會被容器創建對象

與之作用相同的註解還有:

  • @Controller
  • @Service
  • @Repository

這些註解只是語義不同,作用都是一樣的。

使用Bean

要使用這個Bean,我們首先需要創建一個容器:

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);

然後,我們可以從中獲取Pojo這個類型的對象:

context.getBean(Pojo.class)

不僅可以使用Bean的類型獲取Bean,也可以使用Bean的名稱獲取:

context.getBean("pojo");

生命週期方法

有時候,我們需要Bean在創建後或者銷燬前做一些事情:我們可以使用以下兩個註解來實現:

    //創建後執行
    @PostConstruct
    public void init(){ System.out.println("init"); }

    //銷燬前執行
    @PreDestroy
    public void destroy(){ System.out.println("destroy"); }

需要注意的是,這兩個註解都不是Spring提供的,它是JAVA EE的標準,在使用的時候需要添加相關依賴

        <dependency>
            <groupId>javax.annotation</groupId>
            <artifactId>javax.annotation-api</artifactId>
            <version>1.3.2</version>
        </dependency>

自動注入

Spring提供了一個最核心的功能就是依賴注入,也就說,Spring幫我們處理了各個對象之間的依賴關係,當一個對象創建時,Spring會找到這個對象所需要的依賴進行注入,我們只需要在要進行依賴注入的地方做一個標記即可,這個標記就是@Autowired

@Component
public class Bean {

    private Bean1 bean1;

    @Autowired
    public Bean(Bean1 bean1) {
        this.bean1 = bean1;
    }

    public void say(){
        System.out.println("hi");
        bean1.run();
    }
}

這個註解不僅能加在構造函數上,也能放在成員變量、setter方法。
不過如果Bean只有一個構造函數,則可以省略這個註解。

JAVA代碼注入

由於某些類來源於外部,我們無法修改其源碼 所以可以使用java代碼的方式創建後注入

@Configuration
public class Config {
    @Bean
    public Bean1 bean1(){return new Bean1();}
}

處理自動裝配歧義性

在使用容器的時候,難免會遇到需要同類不同實例的對象,那麼這時候又該怎麼辦?

解決方法有兩個:

  • 從生產方解決
  • 從消費方解決
@Bean
@Primary // 標示首選bean
public Bean1 bean1(){
    Bean1 bean1 = new Bean1();
    bean1.setName("pro");
    return bean1;
}
@Autowired
@Qualifier("bean1f") // 當有多個可選項時,將使用名爲bean1f的bean
public void setBean1(Bean1 bean1){}

Bean的作用域

  • singleton:單例,即在整個容器中只會有一個同類型對象
  • prototype:每次獲取都會創建實例
  • session:每個會話一個bean(此處的會話指web容器的會話Session)
  • request:每個請求一個bean(web容器的Request)
  • global session:應用在Portlet環境.如果沒有Portlet環境那麼globalSession相當於session

條件裝配

可能我們的Bean並不是每次都需要創建,那麼則可以使用條件化裝配

@Bean
@Conditional(MyConditional.class)
public Bean1 bean1(){
    Bean1 bean1 = new Bean1();
    bean1.setName("pro");
    return bean1;
}

只要實現Condition接口,就可以控制Bean的創建與否

  public class MyConditional implements Condition {

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {

        return true;
    }
  }

運行時值注入

在運行時,我們可能需要外部配置文件的一些值,我們可以先通過配置類注入配置文件

@Configuration
@ComponentScan(basePackages = "wang.ismy.spring")
@PropertySource("classpath:config.properties")
public class Config { }

在Bean中,可以使用@Value註解注入值

@Component
public class Bean {
  @Value("${name}")
  String name;
}

SPEL

Spring Expression Language(Spring表達式),是一種類似於腳本語言的東西,我們可以通過在@Value中寫一些字符串以此來達到語言級的能力:

@Value("#{T(System).currentTimeMillis()}") // 獲取當前時間
long time;

導入配置

使用@Import可導入其他配置類

@Configuration
@Import({DevConfig.class,ProConfig.class})
public class MasterConfig { }

配置環境

在開發與測試或者生產環境,很多配置都是不一樣的,如果需要頻繁地改,那會是很麻煩的,我們可以爲配置指定一個環境,在不同的場景啓用不同的環境

@Configuration
@Profile(("dev")) // 開發環境配置
public class DevConfig {}
@Configuration
@Profile("pro") // 生產環境配置
public class ProConfig {}

我們需要一個主配置,導入所有的配置:

@Configuration
@Import({DevConfig.class,ProConfig.class})
public class MasterConfig { }

在使用註解上下文時,我們使用這個主配置爲引導類

激活

方法有兩種,一是設置環境變量,二是手動編碼

System.setProperty("spring.profiles.active","dev"); // 通過設置環境變量
// 手動編碼設置
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.getEnvironment().setActiveProfiles("dev");
context.register(MasterConfig.class);
context.refresh();
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章