1.管理bean
之前我們要想管理bean都是在xml文件中將想要添加的bean手動添加進ioc容器中,這樣太過麻煩了,在 Java 開發里,針對一些較為繁瑣的操作,通常會有相應的簡化方式,這個也不例外,就是spring提供的注解。
@Component
只需要把它寫在想要放入ioc容器的bean所屬的類上即可,在后面可以加上(value="")這個value的值就是相當于之前xml文件中bean標簽里的id,可以直接把value去掉直接寫上對應的值,畢竟就這一個值也不需要區分。當然你也可以選擇什么都不加,那么此時默認的值就是改類名但是首部第一個字母一定要是小寫。
還有一個很重要的細節別忘了,就是一定要在xml文件中配置掃描,旨在告訴spring要掃描的包因為ClassPathXmlApplicationContext初始化容器時會把xml文件中聲明的標簽下的類都創建到容器中。但 是因為bean.xml并不知道哪一個類加上注解了,所以無法創建對象。
<context:component-scan base-package="com.xq"></context:component-scan>
base-package的值就是告訴com.xq一下的包都要掃描。?
該注解衍生出三個注解
@Controller:一般用在表現層。
@Service:一般用在業務。
@Repository:一般用在持久層。
其實它們跟@Component是一個用法,之所以這樣分開是因為java寫項目時是需要進行分層開發的
為了區分各個層,就用了這三個注解。
2.依賴注解
@Autowired
有一點要說明,它只能注入引用類型的bean
分三個場景來講
構造函數注入
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;// 定義一個服務接口
interface MessageService {void sendMessage(String message);
}// 實現服務接口
@Component
class EmailService implements MessageService {@Overridepublic void sendMessage(String message) {System.out.println("Sending email: " + message);}
}// 使用 @Autowired 進行構造函數注入
@Component
class UserService {private final MessageService messageService;@Autowiredpublic UserService(MessageService messageService) {this.messageService = messageService;}public void notifyUser(String message) {messageService.sendMessage(message);}
}
在該代碼中,類UserService依賴于MessageService,通過構造函數注入的方式,spring會自動將EmailService的實例注入到UserService中。
setter方法注入
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;// 定義一個服務接口
interface PaymentService {void processPayment(double amount);
}// 實現服務接口
@Component
class CreditCardPaymentService implements PaymentService {@Overridepublic void processPayment(double amount) {System.out.println("Processing credit card payment: " + amount);}
}// 使用 @Autowired 進行 Setter 方法注入
@Component
class OrderService {private PaymentService paymentService;@Autowiredpublic void setPaymentService(PaymentService paymentService) {this.paymentService = paymentService;}public void placeOrder(double amount) {paymentService.processPayment(amount);}
}
這里的OrderService通過setter方法注入了PaymentService實例。
字段注入?
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;// 定義一個服務接口
interface LoggingService {void log(String message);
}// 實現服務接口
@Component
class ConsoleLoggingService implements LoggingService {@Overridepublic void log(String message) {System.out.println("Logging to console: " + message);}
}// 使用 @Autowired 進行字段注入
@Component
class ProductService {@Autowiredprivate LoggingService loggingService;public void addProduct(String productName) {loggingService.log("Adding product: " + productName);}
}
?ProductService類中的loggingService被注入ConsoleLoggingService的實例,但是這里有一點要注意,萬一接口有多個實現類呢,那這樣就會報錯,在識別時ioc容器會先先按照類型進行篩選,如果有多個相同類型的,然后用變量名作為bean的id繼續篩選。
3.其他注入數據的注解
使用注入數據注解的效果跟在xml配置文件中的bean標簽中寫一個標簽的作用是一樣的.
@Qualifier:它可以在按照類中注入的基礎之上再按照名稱注入,但是它給類成員注入時不能單獨使用,但是在給方法參數注入式可以。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;// 定義一個接口
interface Animal {void sound();
}// 實現接口
@Component("dog")
class Dog implements Animal {@Overridepublic void sound() {System.out.println("Woof!");}
}@Component("cat")
class Cat implements Animal {@Overridepublic void sound() {System.out.println("Meow!");}
}// 使用 @Autowired 和 @Qualifier 注入指定的 Bean
@Component
class AnimalService {private final Animal animal;@Autowired@Qualifier("dog")public AnimalService(Animal animal) {this.animal = animal;}public void makeSound() {animal.sound();}
}
將@Autowired和@Qualifier組合在一起,spring會根據類型和@Qualifier指定的名稱從ioc容器中查找對應的bean并注入到AnimalService中。
@resource
它與@Autowired的注入策略相反,它是先看bean的id來篩選,因為它后面可以加(name=“”),再來看類型。
import javax.annotation.Resource;
import org.springframework.stereotype.Component;// 定義一個接口
interface Printer {void print();
}// 實現接口,并使用 @Component 指定 Bean 的名稱為 "colorPrinter"
@Component("colorPrinter")
class ColorPrinter implements Printer {@Overridepublic void print() {System.out.println("Printing in color...");}
}// 使用 @Resource 按名稱注入
@Component
class PrintingService {@Resource(name = "colorPrinter")private Printer printer;public void doPrinting() {printer.print();}
}
這里的@Resource直接指明了bean的id為colorPrinter,spring直接在ioc容器中尋找對應的bean,再將其注入到printer字段中。
@Value
用于注入基本數據類型和String類型,因為前面提到的那些只能注入引用數據類型。可以用在字段、構造函數參數或者方法參數上,用于注入值。
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;@Component
public class MyComponent {@Value("Hello, Spring!")private String message;@Value("123")private int number;public String getMessage() {return message;}public int getNumber() {return number;}
}
通過該注解,可以很方便的將各種外部值注入到spring管理的bean中。
4.改變作用域范圍的注解
@Scope
類似于xml文件中的scope屬性,它是用來注解一個類的
分別是
@Scope(value="singleton")單例bean
@Scope(value="prototype")多例bean
@Service("accountService")
@Scope(value = "prototype")
public class AccountServiceImpl implements AccountService {@Resource(name = "accountDao1")AccountDao accountDao1;public void addAccount() {accountDao1.addAccount();}
}public class TestAccount {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");AccountService accountService1 = (AccountService) context.getBean("accountService");AccountService accountService2 = (AccountService) context.getBean("accountService");System.out.println(accountService1==accountService2);}
}
根據注解顯示創建的是多例bean,所以輸出為false。、
5.生命周期相關的注解
使用與生命周期相關的注解的作用跟在bean標簽中使用init-method和destroy-method的作用是一樣 的。
@PreDestroy 作用:用于指定銷毀方法。
@PostConstruct 作用:用于指定初始化方法。
代碼就不寫了,沒啥寫的,無非就是在相應的方法上加上相應的注解。