聊一聊spring的常用註解

一、@value

javaBean

public class Bird {
	//使用@Value進行賦值:1,基本字符  2,springEL表達式, 3,可以讀取 我們的配置文件
	@Value("James")
	private String name;
	
	@Value("#{20-2}")
	private Integer age;
	
	@Value("${bird.color}")
	private String color;
	
	public Bird() {
		super();
	}
	
	public Bird(String name, Integer age, String color) {
		super();
		this.name = name;
		this.age = age;
		this.color = color;
	}
	
	//getter、setter 方法.......
}

config

@Configuration
//加載 properties 文件
@PropertySource("classpath:/test.properties")
public class Cap8MainConfig {

    @Bean
    public Bird bird(){
        return new Bird();
    }
}

properties

bird.color=red

test

public class Cap8Test {
	@Test
	public void test01(){
		AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Cap8MainConfig.class);

		Bird bird = (Bird) app.getBean("bird");

		System.out.println(bird);
		System.out.println("IOC容器創建完成........");
		
		ConfigurableEnvironment environment = app.getEnvironment();
		System.out.println("environment===="+environment.getProperty("bird.color"));
		app.close();
	}
}

輸出

Bird [name=James, age=18, color=red]
IOC容器創建完成........
environment====red

注:@PropertySource(“classpath:/test.properties”) 會把properties 配置文件中的標量都掃進環境變量中,@Value("${bird.color}")去環境變量中取值

二、註解方式 聲明 bean 與注入 bean

1.聲明bean的註解

@Component 組件,沒有明確的角色
@Service 在業務邏輯層使用(service層)
@Repository 在數據訪問層使用(dao層)
@Controller 在展現層使用,控制器的聲明(C)

注:以上註解納入 springBean中,默認bean的Id是類名首字母小寫,可選參數 value 可指定自定義 bean Id,如下:
如果是①,那麼這個 service 的 bean Id 就是 TtetService
如果是②,那麼 service 的 bean Id就是myTestService

//@Service(value = "myTestService") //②
@Service   //①
public class TestService{
    
}

2、注入bean的註解

@Autowired:由Spring提供
@Inject:由JSR-330提供
@Resource:由JSR-250提供
都可以註解在set方法和屬性上,推薦註解在屬性上(一目瞭然,少寫代碼)。

@Autowired

1.@Autowired 是 spring 註解
2.@Autowired註解是按照類型(byType)裝配依賴對象.
3.默認情況下它要求依賴對象必須存在,如果允許null值,可以設置它的required屬性爲false。
4.如果我們想使用按照名稱(byName)來裝配,可以結合@Qualifier註解一起使用。
5.可以設置屬性@Autowired(required = false),表示如果沒有接口的實現類,那麼就注入 null
接口:

public interface ITestService {
    void judgeService();
}

service 實現類1 TestService

@Service
public class TestService implements ITestService{
	private TestDao testDao;

	@Override
	public void judgeService() {
		System.out.println("this is service");
	}
}

service 實現類2 TestService2

@Service
public class TestService2 implements ITestService{
	@Override
	public void judgeService() {
		System.out.println("this is service2");
	}
}

controller1

@Controller
public class TestController {
	@Qualifier("testService2")
	@Autowired(required = true)
	private TestService testService;

	public void testSwichService(){
		testService.judgeService();
	}

}

controller2

@Controller
public class TestController {
	@Autowired(required = true)
	private ITestService iTestService;

	public void testSwichService(){
		iTestService.judgeService();
	}

}

controller3

@Controller
public class TestController {
	@Qualifier("testService2")
	@Autowired(required = false)
	private ITestService iTestService;

	public void testSwichService(){
		iTestService.judgeService();
	}

}

test

public class Cap9Test {
	@Test
	public void test01(){
		AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Cap9MainConfig.class);

		TestController testController = app.getBean(TestController.class);
		testController.testSwichService();


	}
}

說明:
1.如果執行的是 controller1,因爲注入的 service 類型定是具體的實現類 TestService,所以@Autowired通過 byType 可以確定的 service 是TestService,所以輸出的是『this is service2』

2.如果執行的是 contoller2,因爲注入的是一個接口ITestService:
           如果沒有TestService2,ITestService的實現類就只有TestService,所以會正常的輸出『this is service』
           現在ITestService有兩個實現類 TestService、TestService2,所以@Autowired就會不知道該注入哪個實現類,最後會報錯:發現了兩個實現類

3.如果執行的是 controller3,同樣注入的是一個接口ITestService,因爲有註解@Qualifier(“testService2”),代表指定ITestService接口實現類的 bean Id,且必須是實現了接口ITestService的 service,因爲此時@Autowired(required = false),所以找不到的話iTestService會爲 Null,不會報錯

@Resource

1.jdk 自帶註解,由JSR-250提供
2.默認按照 name(實際是 beanId)進行裝配,如果name匹配不到才按 type進行匹配。需要注意的是,如果只按 name 匹配,如果 name 匹配不到,就不會按照類型就行匹配了,會報找不到。
3.必須有一個合適的實現類注入進來,不然會報錯

接口

public interface ITestService {
    void judgeService();
}

service 實現類1 TestService

@Service
public class TestService implements ITestService{
	@Override
	public void judgeService() {
		System.out.println("this is service");
	}
}

service 實現類2 TestService2

@Service
public class TestService2 implements ITestService{
	@Override
	public void judgeService() {
		System.out.println("this is service2");
	}
}

controller

@Controller
public class TestController {
    //所掃描的 bean 必須爲ITestService的實現類

    //查找 beanId 爲 『testService』的 bean
	@Resource(name = "testService")
	
	//查找類型爲『TestService.class』的 bean
	@Resource(type = TestService.class)
	
	//查找 beanId 爲 『testService』且類型爲『TestService.class』的 bean
	@Resource(name = "testService",type = TestService.class)
	private ITestService iTestService;

	public void testSwichService(){
		iTestService.judgeService();
	}

}

注:Resource 也可以使用 @Qualifier,但是 Resource 本身可以設置 name 屬性,再使用@Qualifier多餘,所以一般沒人這樣用的

@Qualifier、@Primary

@Qualifier(“xxxx”):幫助註解 byName
@Primary:用在聲明註解,在注入接口,且接口有多個實現類,在無法唯一判斷注入哪個具體的實現類時,注入標記了@Primary的實現類(只能有一個實現類加入這種標記)

接口

public interface ITestService {
    void judgeService();
}

service 實現類1 TestService

@Primary
@Service
public class TestService implements ITestService{
	private TestDao testDao;

	@Override
	public void judgeService() {
		System.out.println("this is service");
	}
}

service 實現類2 TestService2

@Service
public class TestService2 implements ITestService{
	@Override
	public void judgeService() {
		System.out.println("this is service2");
	}
}

controller1

@Controller
public class TestController {
	@Autowired
	private ITestService iTestService;

	public void testSwichService(){
		iTestService.judgeService();
	}

}

controller2

@Controller
public class TestController {
	@Qualifier("testService2")
	@Autowired
	private ITestService iTestService;

	public void testSwichService(){
		iTestService.judgeService();
	}

}

test

public class Cap9Test {
	@Test
	public void test01(){
		AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Cap9MainConfig.class);

		TestController testController = app.getBean(TestController.class);
		testController.testSwichService();


	}
}

如果執行 controller1, controller未指明具體注入哪個實現類,所以 注入標記了@Primary 的 service,最後輸出『this is service』
如果執行controller2,controller 使用@Qualifier(“testService2”),指明瞭注入的 beanId ,所以最終輸出爲『this is service2』

@Autowired和@Resource 的區別

相同點
1.兩個都是注入 bean 的註解
2.都支持@Qualifier、@Primary 註解(看過教程說 @Resource不支持@Primary,但是經過實驗,是支持的)

不同點:
1.Autowired是 spring 的註解,Resource 是 jdk 的註解
2.Autowired有 require=false,如果找不到實現類就注入空。Resource 沒有這種屬性,找不到就報錯
3.Autowired 只能默認通過 byType注入。Resource 可以通過 name、type 屬性 來指定 byType、byName 注入。


特別的:在注入 bean 時,不管是 @Autowired、@Resource或是@Inject,都可以不靠@Qualifier、@Primary,或是@Resource的 name、type 屬性來輔助注入唯一的實現類。只需要通過注入時的變量與 註冊到 spring 容器中的 Bean Id 來對應即可,實際是利用 ByName 的屬性:

接口:

public interface ITestService {
    void judgeService();
}

service 實現類1 TestService

@Service
public class TestService implements ITestService{

	@Override
	public void judgeService() {
		System.out.println("this is service");
	}
}

service 實現類2 TestService2

@Service
public class TestService2 implements ITestService{
	@Override
	public void judgeService() {
		System.out.println("this is service2");
	}
}

controller

@Controller
public class TestController {
	@Autowired
//	@Resource
//  @Inject

    //此處的變量名,需要與想要注入的實現類的 beanId 相同
	private ITestService TestService2;

	public void testSwichService(){
		TestService2.judgeService();
	}

}

最後輸出結果:『this is service2』

未完,持續更新中。。。。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章