Spring-05 使用註解開發
使用註解開發
1.專案準備
在spring4之後,想要使用註解形式,必須得要引入aop的包5
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.3.3</version>
</dependency>
在配置檔案當中,還得要引入一個context約束
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
</beans>
2.Bean實現
我們之前都是使用 bean 的標籤進行bean注入,但是實際開發中,我們一般都會使用註解!
1、配置掃描哪些包下的註解
<context:component-scan base-package="pojo"/>
2、在指定包下編寫類,增加註解
// 相當於配置檔案中 <bean id="user" class="當前註解的類"/>
@Component("user")
public class User {
public String name = "zc";
}
3.測試
@Test
public void UserTest(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
User user = (User) applicationContext.getBean("user");
System.out.println(user.name);
}
3.屬性注入
3.1 不提供set方法
可以不提供set方法
,直接在屬性名上新增@value(“xxx”)
@Component("user")
public class User {
// 相當於配置檔案中 <property name="name" value="秦疆"/>
@Value("zc")
public String name;
}
測試結果成功
3.1 提供了set方法
如果提供了set方法
,在set方法上新增@value(“xxx”)
@Component("user")
public class User {
public String name;
@Value("zc")
public void setName(String name) {
this.name = name;
}
}
測試結果成功
4.衍生註解
我們這些註解,就是替代了在配置檔案當中配置步驟而已!更加的方便快捷!
@Component三個衍生註解
為了更好的進行分層,Spring可以使用其它三個註解,功能一樣,目前使用哪一個功能都一樣。
- @Controller:web層
- @Service:service層
- @Repository:dao層
寫上這些註解,就相當於將這個類交給Spring管理裝配了!
作用域
@scope
- singleton:預設的,Spring會採用單例模式建立這個物件。關閉工廠 ,所有的物件都會銷燬。
- prototype:多例模式。關閉工廠 ,所有的物件不會銷燬。內部的垃圾回收機制會回收
@Component("user")
@Scope("prototype")
public class User {
@Value("zc")
public String name;
}
總結
XML與註解比較
- XML可以適用任何場景 ,結構清晰,維護方便
- 註解不是自己提供的類使用不了,開發簡單方便
xml與註解整合開發 :推薦最佳實踐
- xml管理Bean
- 註解完成屬性注入
- 使用過程中, 可以不用掃描,掃描是為了類上的註解
<context:annotation-config/>
作用:
- 進行註解驅動註冊,從而使註解生效
- 用於啟用那些已經在spring容器裡註冊過的bean上面的註解,也就是顯示的向Spring註冊
- 如果不掃描包,就需要手動配置bean
- 如果不加註解驅動,則注入的值為null
5.使用java的方式配置Spring
我們現在要完全不使用spring的xml配置,全權交給java來做。
5.1 實體類
@Controller
public class UserT {
// 屬性的注入
@Value("zcT")
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
}
5.2 配置類
@Configuration:本質上也是一個Controller,也會被spring託管,註冊到容器中
@Configuration:表示這是一個配置類,和之前的beans.xml的功能一樣的
@ComponentScan:表示元件的掃描
@import:匯入其他的配置類
@Bean:表示註冊一個bean
@Configuration
@ComponentScan("pojo")
public class MyConfig {
// 方法的名字即是bean中的id
// 方法的返回值就是bean中的class
@Bean
public UserT getUserT(){
return new UserT(); // return就是返回要注入到bean中的物件
}
}
5.3 測試
@Test
public void UserTTest(){
ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
UserT userT = (UserT) context.getBean("getUserT");
System.out.println(userT.toString());
}
代理模式
為什麼要學習代理模式,因為AOP的底層機制就是動態代理。
代理模式:
- 靜態代理
- 動態代理
1.靜態代理
角色分析
- 抽象角色 : 一般使用介面或者抽象類來實現
- 真實角色 : 被代理的角色
- 代理角色 : 代理真實角色 ; 代理真實角色後 , 一般會做一些附屬的操作
- 客戶 : 使用代理角色來進行一些操作
1.1 案例分析
1.1.1 介面類
public interface Rent {
public void rent();
}
1.1.2 實體類
//房東
public class Host implements Rent{
public void rent() {
System.out.println("出租房子");
}
}
//代理類
public class Proxy implements Rent{
private Host host;
public Proxy(){
}
public Proxy(Host host){
this.host = host;
}
// 因為要幫房東租房子,所以代理也要實現租房子
public void rent() {
host.rent();
}
//看房
public void seeHouse(){
System.out.println("帶房客看房");
}
//收中介費
public void fare(){
System.out.println("收中介費");
}
}
1.1.3 測試實體類
public class Client {
public static void main(String[] args) {
// 房東要租房
Host host = new Host();
// 中介幫房東
Proxy proxy = new Proxy(host);
// 去找中介
proxy.rent();
}
}
分析:在這個過程中,你直接接觸的就是代理類(Proxy),就如同現實生活中的樣子,你看不到房東,但是你依舊通過中介,租到了房東的房子,這就是所謂的代理模式。
靜態代理的好處:
- 可以使得我們的真實角色更加純粹 . 不再去關注一些公共的事情 .
- 公共的業務由代理來完成 . 實現了業務的分工 ,
- 公共業務發生擴充套件時變得更加集中和方便 .
缺點 :
- 類多了 , 多了代理類 , 工作量變大了 . 開發效率降低 .
我們在不改變原來的程式碼的情況下,實現了對原有功能的增強,這是AOP中最核心的思想。
2.動態代理
-
動態代理的角色和靜態代理的一樣 .
-
動態代理的代理類是
動態生成
的,靜態代理的代理類是我們提前寫好
的 -
動態代理分為兩類 : 一類是基於介面動態代理 , 一類是基於類的動態代理
-
- 基於介面的動態代理----JDK動態代理
- 基於類的動態代理--cglib
- 現在用的比較多的是 javasist 來生成動態代理
- 我們這裡使用JDK的原生程式碼來實現
2.1 JDK的動態代理需要了解兩個類
核心 : InvocationHandler 和 Proxy
【InvocationHandler:呼叫處理程式】
Object invoke(Object proxy, 方法 method, Object[] args);
//引數
//proxy - 呼叫該方法的代理例項
//method -所述方法對應於呼叫代理例項上的介面方法的例項。方法物件的宣告類將是該方法宣告的介面,它可以是代理類繼承該方法的代理介面的超級介面。
//args -包含的方法呼叫傳遞代理例項的引數值的物件的陣列,或null如果介面方法沒有引數。原始型別的引數包含在適當的原始包裝器類的例項中,例如java.lang.Integer或java.lang.Boolean 。
【Proxy : 代理】
//生成代理類
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
rent.getClass().getInterfaces(),this);
}
2.2 案例分析
2.2.1 介面類
//抽象角色:租房
public interface Rent {
public void rent();
}
2.2.2 實體類
//房東
public class Host implements Rent{
public void rent() {
System.out.println("出租房子");
}
}
2.2.3 代理類
public class ProxyInvocationHandler implements InvocationHandler {
private Rent rent;
public void setRent(Rent rent) {
this.rent = rent;
}
//生成代理類,重點是第二個引數,獲取要代理的抽象角色!之前都是一個角色,現在可以代理一類角色
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
rent.getClass().getInterfaces(),this);
}
// proxy : 代理類 method : 代理類的呼叫處理程式的方法物件.
// 處理代理例項上的方法呼叫並返回結果
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//核心:本質利用反射實現!
Object result = method.invoke(rent, args);
fare();
return result;
}
//看房
public void seeHouse(){
System.out.println("帶房客看房");
}
//收中介費
public void fare(){
System.out.println("收中介費");
}
}
2.2.4 測試實體類
public class Client {
public static void main(String[] args) {
//真實角色
Host host = new Host();
//代理例項的呼叫處理程式
ProxyInvocationHandler pih = new ProxyInvocationHandler();
pih.setRent(host); //將真實角色放置進去
Rent proxy = (Rent)pih.getProxy(); //動態生成對應的代理類
proxy.rent();
}
}
一個動態代理 , 一般代理某一類業務 , 一個動態代理可以代理多個類,代理的是介面
2.3 動態代理的好處
靜態代理有的它都有,靜態代理沒有的,它也有!
- 可以使得我們的真實角色更加純粹 . 不再去關注一些公共的事情 .
- 公共的業務由代理來完成 . 實現了業務的分工 ,
- 公共業務發生擴充套件時變得更加集中和方便 .
- 一個動態代理 , 一般代理某一類業務
- 一個動態代理可以代理多個類,代理的是介面!
個人部落格為:
MoYu's Github Blog
MoYu's Gitee Blog