元件是根據實際情況來配置的。比如一個類,是做業務處理的,那就用@service元件
要在xml加入context命名空間
<!-- 指定Spring IOC容器掃描的包 -->
<context:component-scan base-package="package com.guigu.spring.beans.annotation"></context:component-scan>
這樣,就表示要自動掃描 基類包的類以及子包中的類。類中有注解,就會被管理
例子:
目錄結構如下,第一個annotation包為要掃描的包,有下面三個子包:controller、repository、service
類裡面都是一個簡單的注解和一個方法:
TestObject.java
package com.guigu.spring.beans.annotation;
import org.springframework.stereotype.Component;
@Component
public class TestObject {
}
UserController.java
package com.guigu.spring.beans.annotation.controller;
import org.springframework.stereotype.Controller;
@Controller
public class UserController {
public void execute(){
System.out.println("UserController execute...");
}
}
//UserRepository.java
package com.guigu.spring.beans.annotation.repository;
public interface UserRepository {
void save();
}
//UserRepositoryImpl.java 繼承 UserRepository
package com.guigu.spring.beans.annotation.repository;
import org.springframework.stereotype.Repository;
@Repository("userRepository");
public class UserRepositoryImpl implements UserRepository {
@Override
public void save() {
System.out.println("UserRepositoryImpl Save...");
}
}
寫一個繼承,為了說明注解命名可以更改,這裡改成了userRepository,否則是預設的userRepositoryImpl,下面講。
//UserService.java
package com.guigu.spring.beans.annotation.service;
import org.springframework.stereotype.Service;
@Service
public class UserService {
public void add(){
System.out.println("UserService add...");
}
}
xml最上面已經配置,最後main函數:
package com.guigu.spring.beans.annotation;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.guigu.spring.beans.annotation.controller.UserController;
import com.guigu.spring.beans.annotation.repository.UserRepository;
import com.guigu.spring.beans.annotation.service.UserService;
public class Main {
public static void main(String[] args) {
ApplicationContext ctx =new ClassPathXmlApplicationContext("beans-annotation.xml");
TestObject to = (TestObject) ctx.getBean("testObject");
System.out.println(to);
UserController userController=(UserController) ctx.getBean("userController");
System.out.println(userController);
UserService userservice=(UserService) ctx.getBean("userservice");
System.out.println(userservice);
UserRepository userRepository=(UserRepository) ctx.getBean("userRepository");
System.out.println(userRepository);
}
}
輸出如下:說明對象被建立了
xml裡面沒有bean,那main函數怎麼擷取Bean呢?
就是用最上面圖中藍色字型。Spring預設命名,名字是它的類名第一個字元小寫。如:
UserService.java類中類名是UserService ,擷取bean預設名字就是userService
也可以更改,如上面的UserRepositoryImpl類,用了@Repository(“userRepository”),表示bean名字為userRepository
在xml中,有一些屬性和節點:
resource-pattern:隻掃描特定檔案
context:include-filter: 子節點表示要包含的元件
context:exclude-filter: 子節點表示要排除在外的元件
<!-- 可以通過resource-pattern指定掃描的資源 -->
<context:component-scan base-package="package com.guigu.spring.beans.annotation"
resource-pattern="repository/*.class">
</context:component-scan>
這樣,隻會掃描repository包下的類,如果main函數中,還要調用其他類,報錯。隻能調用repository包下的類。
<!-- context:exclude-filter 子節點指定排除哪些指定表達式的元件 -->
<context:component-scan base-package="package com.guigu.spring.beans.annotation">
<context:exclude-filter type="annotation" expression="package com.guigu.spring.beans.annotation.repository"/> //type類型後面看
</context:component-scan>
這表示不掃描repository子包的檔案,若main函數中調用它們,會抛異常
<!-- context:include-filter 子節點指定包含哪些指定表達式的元件, 該子節點需要use-default-filters配合使用 -->
<context:component-scan base-package="package com.guigu.spring.beans.annotation"
use-default-filters="false">
<context:include-filter type="annotation"
expression="package com.guigu.spring.beans.annotation"/>
</context:component-scan>
注意,use-default-filters預設自動掃描全部,要設定成false不自動掃描,才能實作隻掃描部分的功能。
context:include-filter和context:exclude-filter子節點支援多種類型的過濾表達式:
@Autowired:自動裝配具有相容類型的單個bean屬性。可以對類成員變量、方法及構造函數進行标注,完成自動裝配的工作。 通過 @Autowired的使用來代替set方法。(property 屬性通過調用setter方法進行指派)
意思就是用它,可以代替xml中的 這樣的引用指派。自動建立bean。
例子:Person類有Car對象,不用 自動裝配
//Person類
public class Person {
private Car car;
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
}
//Car類
public class Car {
private String brand;
private double price;
public void setBrand(String brand) {
this.brand = brand;
}
public void setPrice(double price) {
this.price = price;
}
}
xml
<bean id="person" class="com.guigu.spring.bean.Person">
<property name="car" ref="car"/>
</bean>
<bean id="car" class="com.guigu.spring.bean.Car">
<property name="brand" value=" aodi"/>
<property name="price" value="200000"/>
</bean>
main
ApplicationContext context = new ClassPathXmlApplicationContext("autowired.xml");
Person person=(Person)ctx.getBean("person");
System.out.println(person);
這是之前的做法。
@Autowired自動裝配的方法
查了一下,在之前版本的Spring中,要使用@Autowired,要在xml寫上這一行代碼才行
<!-- 該 BeanPostProcessor 将自動對标注 @Autowired 的 Bean 進行注入 -->
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
但現在spring4,context:component-scan自動注冊AutowiredAnnotationBeanPostProcessor執行個體,可以使用@Autowired和@Resource、和@Inject注解(一般用@Autowired)
是以,如果使用了context:component-scan,就不用額外注冊,不然還是要
//Person類
public class Person {
//@Aotuwired //自動根據xml配置執行個體car對象
private Car car;
}
<bean id="person" class="com.guigu.spring.bean.Person">
//這裡就不需要再寫ref="car"
</bean>
<bean id="car" class="com.guigu.spring.bean.Car">
<property name="brand" value=" aodi"/>
<property name="price" value="200000"/>
</bean>
結果和不用 @Aotuwired一樣,都可以
還可以寫在setter上
//Person類
public class Person {
private Car car;
//@Aotuwired
public Car setCar(Car car){
this.car=car;
}
}
回到注解上面的例子:
//UserController.java
package com.guigu.spring.beans.annotation.controller;
import org.springframework.stereotype.Controller;
@Controller
public class UserController {
public void execute(){
System.out.println("UserController execute...");
}
}
// main函數
public class Main {
public static void main(String[] args) {
private UserController userController;
ApplicationContext ctx =new ClassPathXmlApplicationContext("beans-annotation.xml");
userController.execute(); // 報錯
}
}
在main函數聲明userController然後直接調用它的方法,這樣顯然不行,因為userController都還沒有建立,這時用@Autowired就很簡單
// main函數
public class Main {
public static void main(String[] args) {
//@Autowired
private UserController userController;
ApplicationContext ctx =new ClassPathXmlApplicationContext("beans-annotation.xml");
userController.execute();//不報錯
}
}
這樣,就自動配置建立了userController對象,可以直接使用
注意①:@Autowired要想成功配置,得先掃描得到,就是UserController類一定要能被掃描到。
注意②:@Autowired遇到相同兩個類
//UserRepository
package com.guigu.spring.beans.annotation.repository;
public interface UserRepository {
void save();
}
//UserRepositoryImpl 繼承 UserRepository
package com.guigu.spring.beans.annotation.repository;
import org.springframework.stereotype.Repository;
@Repository("userRepository"); //這裡
public class UserRepositoryImpl implements UserRepository {
@Override
public void save() {
System.out.println("UserRepositoryImpl Save...");
}
//UserRepositoryImpl2 繼承 UserRepository
@Repository
public class UserRepositoryImpl2 implements UserRepository {
@Override
public void save() {
System.out.println("UserRepositoryImpl2 Save...");
}
}
// main函數
public class Main {
public static void main(String[] args) {
//@Autowired
private UserRepository userRepository ;
ApplicationContext ctx =new ClassPathXmlApplicationContext("beans-annotation.xml");
userRepository .save();
}
}
main函數中有@Autowired,自動建立對象,但UserRepository 類卻有兩個接口,它要去建立哪一個呢?
:預設情況下,若有兩個,去找名字相同的,就是還沒執行個體的這個userRepository ,若找到和它名字一樣的,上面 @Repository(“userRepository”); 寫了名字,那就找它了。
若不是這樣寫@Repository(“userRepository”);而是 @Repository(),那就報錯了。
注意③:解決②的另一個方法
若@Repository(“userRepository”);改成@Repository(),main函數會報錯。
改一下main函數
// main函數
public class Main {
public static void main(String[] args) {
//@Autowired
//Qualifier("userRepositoryImpl ")
private UserRepository userRepository ;
ApplicationContext ctx =new ClassPathXmlApplicationContext("beans-annotation.xml");
userRepository .save();
}
}
用Qualifier("userRepositoryImpl ");表示去找userRepositoryImpl 執行個體,這樣也解決了。