天天看點

全注解下的Spring IOC一,建立Bean的兩種方法

文章目錄

  • 一,建立Bean的兩種方法
    • 1,使用@Bean注解來建立Bean
    • 2,通過掃描裝配Bean
  • IoC是種通過描述來生成或者擷取對象的技術,而這個技術不是Spring甚至不是java獨有的。對于Java初學者更多的時候所熟悉的是使用new關鍵字來建立對象,而在Spring中則不是,它是通過描述來建立對象。因為Spring Boot并不建議使用XML,而是通過注解的描述生成對象,是以本文主要是通過注解來介紹Spring IoC技術。
  • 一個 系統可以生成各種對象, 并且這些對象都需要進行管理。還值得一提的是,對象之間并不是孤立的,它們之間還可能存在依賴的關系。例如,一 個班級是由多個老師和同學組成的,那麼班級就依賴于多個老師和同學了為此Spring還提供了依賴注入的功能,使得我們能夠通過描述來管理各個對象之間的關系。

    為了描述上述的班級、同學和老師這3個對象關系,我們需要個容器, 在spring中把每個需要管理的對象稱為sping Bean (簡稱Bean) 。而spring管理這些Bean的容器,被我們稱為Spring IoC容器(或者簡稱loC容器). IoC容器需要具備兩個基本的功能:

  • 通過描述管理Bean, 包括釋出和擷取Bean;,
  • 通過描述完成Bean之間的依賴關系。

一,建立Bean的兩種方法

1,使用@Bean注解來建立Bean

在Spring Boot中我們主要是通過注解來裝配Bean到Spring IOC容器中,為了貼近Spring Boot的需要,我們不在介紹與XML相關的IOC容器,而主要介紹一個基于注解的IOC容器,他就是AnnotationConfigApplicationContext,從名稱就可以看出他是一個基于注解的IOC容器。

第一步:建立一個java類(POJO)檔案:User.java

package com.atstudying.demo;

public class User {

    private int number;
    private String name;
    private String place;

/**
setterAndgetterWay
*/
           

第二步:在定義一個Java配置檔案 檔案:UserConfiguration.java

package configuration;
import com.atstudying.demo.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration//代表這是一個java配置檔案,Spring容器會根據它來生成IOC容器去裝配Bean
public class UserConfiguration {

    @Bean(name="user")//代表initUser方法傳回的POJO裝配到ioc容器中,而其屬性name定義這個bean名稱,如果沒有配置它,則将方法名稱“initUser”作為Bean的名稱儲存到SpringIOC容器中
    public User initUser(){

        User user=new User();
        user.setName("zlj");
        user.setNumber(1);
        user.setPlace("beijing");
        return user;

    }

}
           

@Configuration//代表這是一個java配置檔案,Spring容器會根據它來生成IOC容器去裝配Bean

@Bean(name=“user”)//代表initUser方法傳回的POJO裝配到ioc容器中,而其屬性name定義這個bean名稱,如果沒有配置它,則将方法名稱“initUser”作為Bean的名稱儲存到SpringIOC容器中

第三步:使用AnnotationConfigApplicationContext來建構自己的IOC容器

package com.atstudying.demo;
import configuration.UserConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import java.util.logging.Logger;

@SpringBootApplication
public class IOCTest {

	private static Logger logger=Logger.getLogger(String.valueOf(IOCTest.class));
	public static void main(String[] args) {

		AnnotationConfigApplicationContext annotationConfigApplicationContext=new AnnotationConfigApplicationContext(UserConfiguration.class);
		User user=annotationConfigApplicationContext.getBean(User.class);

		logger.info("姓名:"+user.getName());

	}

}
           

代碼中将java配置檔案UserConfiguration.java傳遞給AnnotationConfigApplicationContext的構造方法,這樣他就可以讀取配置。然後将配置裡面的Bean裝配到IOC容器,于是可以使用getBean方法擷取對應的POJO,運作後可以看到如下日志

全注解下的Spring IOC一,建立Bean的兩種方法

2,通過掃描裝配Bean

  • 在Spring中允許我們通過XML或者Java配置檔案裝配Bean,但是由于Spring Boot是基于注解的方式,是以下面主要基于注解的方式來介紹Spring的用法,以滿足Spring Boot開發者的需要。
  • 如果一個個的Bean使用注解@Bean注入Spring IoC 容器中,那将是一件很麻煩的事情。好在Spring還允許我們進行掃描裝配Bean到IoC容器中,對于掃描裝配而言使用的注解是@Component和@ComponentScan. @Component是标明哪個類被掃描進入Spring loC容器,而**@ComponentScaon**則是标明采用何種政策去描裝配Bean。

第一步:在com.configuration内建立檔案:User_Component.java

package configuration;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component("UserConfiguration")
public class User_Component {

    @Value("2")
        private int number;
    @Value("lqx")
        private String name;
    @Value("hubei")
        private String place;
/**
setter和getter方法
/
}

           

這裡的注解 @Component :表明這個類将被Spring IoC容器掃描裝配,其中配置的"UserConfiguration”則是作為Bean的名稱,當然你也可以不配置這個字元串,那麼IoC容器就會把類名第一個字母作為小寫,其他不變作為Bean名稱放入到IoC容器中; 注解 @Value則是指定具體的值,使得Spring IoC給予對應的屬性注入對應的值。

第二步:為了讓Spring IoC容器裝配這個類,需要改造類UserConfiguration.java。

package configuration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan
public class UserConfiguration_Component {
}
           

這裡加入了 @ComponentScan,意味着它會進行掃描,但是他隻會掃描類UserConfiguration所在的目前包和其子包。之前在com.configuration内建立檔案:User_Component.java

就是這個原因。

第三步:測試

package com.atstudying.demo;

		import configuration.UserConfiguration_Component;
		import configuration.User_Component;
		import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import java.util.logging.Logger;

@SpringBootApplication
public class IOCTest {

	private static Logger logger=Logger.getLogger(String.valueOf(IOCTest.class));
	public static void main(String[] args) {

		AnnotationConfigApplicationContext annotationConfigApplicationContext=new AnnotationConfigApplicationContext(UserConfiguration_Component.class);
		User_Component user=annotationConfigApplicationContext.getBean(User_Component.class);

		logger.info("姓名:"+user.getName());

	}

}
           

代碼中将java配置檔案UserConfiguration_Component.java傳遞給AnnotationConfigApplicationContext的構造方法,這樣他就可以讀取配置。然後将配置裡面的Bean裝配到IOC容器,于是可以使用getBean方法擷取對應的POJO,運作後可以看到如下日志

全注解下的Spring IOC一,建立Bean的兩種方法

問題1:

為了使得User_Component類可以被掃描到,我們把它遷移到了不該放置他的配置包configuration,這樣不太合理。為了更加合理,@ComponentScan還允許我們自定義掃描的包

  • 可以通過配置項basePackages定義掃描的包名,在沒有定義的情況下,它隻會掃描目前包和其子包下的路徑;還可以通過配置項basePackageClasses 定義掃描的類;。其中還有includeFilters 和excludeFilters, includeFilters 是定義滿足過濾器(Filter) 條件的Bean才去掃描,excludeFilters 則是排除過濾器條件的Bean,它們都需要通過一個注解@Filter去定義,它有一個 type類型,這裡可以定義為注解或者正則式等類型。classes定義注解類,pattern 定義正則式類。

此時我們再把User_Component類放到包POJO中,這樣User_Component類和UserConfiguration_Component類就不再同包,那麼我們把AppConfg中的注解修改為:

@ComponentScan ("POJO.*")
或
@ComponentScan (basePackages=
{"POJO"})
或
@ComponentScan (basePackageClasses=
{"User_Component.class"})
           

不管采用上述何種方式,都可以讓ioc容器去掃描User_Component類。

問題2:

當是有時候我們的需求是想掃描一些包,将一些Bean配置到Spring IOC容器中,而不是想加載這個包裡面的Bean。比如我們有一個UserService類,為了标注她為服務類,将類标注@Service(該标準注入@Component,是以在預設情況下它會被Spring掃描裝配到IOC容器中)為了不被裝配,需要把掃描的政策改為

@Configuration
@ComponentScan(basePackages = "com.atstudying.demo.*",excludeFilters = {@ComponentScan.Filter(classes = {UserService.class})})
           

由于加入了excludeFilters 的配置,讓标注了@Service的類不可以被IOC容器掃描注入,這樣就把UserService類排除到SpringIOC容器中了

UserService.java

package com.atstudying.demo.UserService;
import org.springframework.stereotype.Service;
import configuration.User_Component;

@Service
class UserService {

    public void printUser(User_Component user){

        System.out.print("姓名:"+user.getName());
        System.out.print("學号:"+user.getNumber());
        System.out.print("位置:"+user.getPlace());

    }
}
           

繼續閱讀