spring的兩大思想:IOC與AOP
一、ioc的概念
什么叫控制翻轉?
之前:
對象的使用方,創建對象,對象的控制權,在對象的使用方手中.
spring:
對象的控制權交給了spring.
舉個例子:智能駕駛,之前車的使用權在人手中,而現在在ai手中,這就是控制反轉.
什么叫ioc:
之前車企生產車需要做整個車,費事費力無法定制化,而現在車企將輪胎輪轂車底等外包給別人做,自己制作組裝:
二、DI
本質上就是想在不new的基礎上完成對象引入,目的是解耦.
依賴注入分為三種:
1.屬性注入
@Autowiredprivate StudentController studentController;public void say(){System.out.println("helloworld");studentController.say();}
@Autowired就是屬性注入的注釋\
正常來說應該是
這樣,但是加了屬性注入注釋就將這個注入到這個對象中了.
// 1. 定義一個服務類(被依賴的對象)
@Service // 告訴Spring:這是一個服務,需要被容器管理
public class UserService {public void doService() {System.out.println("執行服務邏輯");}
}// 2. 定義控制器(需要依賴的對象)
@Controller // 告訴Spring:這是一個控制器,需要被容器管理
public class UserController {// 3. 聲明依賴:告訴Spring,我需要一個UserService對象@Autowired private UserService userService;public void doController() {// 直接使用注入的對象,不用自己newuserService.doService(); }
}
@Autowired會根據名稱進行注入,如果服務類中有多個名字對不上的該怎么辦呢?有三種方法:
@Autowired與@Resource的區別:
1.注入順序
? @Autowired
:默認按類型(Type)匹配注入。
- 先根據字段 / 參數的類型在 Spring 容器中查找匹配的 Bean。
- 如果存在多個同類型的 Bean,需要配合?
@Qualifier
?注解按名稱(Name)篩選,否則會報錯。
示例:@Autowired @Qualifier("userServiceA") // 指定名稱為userServiceA的Bean private UserService userService;
@Resource
:默認按名稱(Name)匹配注入,名稱可以通過?name
?屬性指定。 - 若未指定?
name
,則默認使用字段名或 setter 方法名作為 Bean 名稱。 - 若按名稱找不到匹配的 Bean,會 fallback 到按類型匹配。
示例:@Resource(name = "userServiceA") // 直接指定Bean名稱 private UserService userService;// 未指定name時,默認按字段名"userService"查找 @Resource private UserService userService;
2.來源
@Autowired是spring提供的注釋,@Resource是JDK提供的注釋.
2.構造方法注入
通過構造方法進行注入
package com.example.demo;import org.springframework.stereotype.Controller;// 控制器類(需要依賴的對象)
@Controller
public class UserController {// 依賴的服務對象,使用final修飾確保不可變private final UserService userService;// 構造方法注入:通過構造方法傳入依賴// Spring會自動找到匹配的UserService對象注入進來public UserController(UserService userService) {this.userService = userService;}public void showUserName() {// 使用注入的依賴對象System.out.println("用戶名:" + userService.getUserName());}
}
總所周知,構造方法可以有無參和有參,這是怎么告訴spring哪個是我們想要的:
@Controller
public class UserController {private final UserService userService;// 無參構造方法(手動定義)public UserController() {// 注意:如果用無參構造創建對象,userService會為nullthis.userService = null;}// 有參構造方法(用于注入依賴)@Autowired // 必須添加,否則Spring會優先用無參構造public UserController(UserService userService) {this.userService = userService;}public void doSomething() {userService.doService(); // 只有通過有參構造創建的對象才能正常調用}
}
3.setter方法注入
package com.example.demo;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;@Controller
public class UserController {private UserService userService;// setter方法注入:通過setter方法傳入依賴@Autowired // 標注在setter方法上public void setUserService(UserService userService) {this.userService = userService;}public void showUserName() {// 使用注入的依賴對象System.out.println("用戶名:" + userService.getUserName());}
}
三、bean的存儲
將對象交給spring進行管理可以使用下面的這些注釋:
類注解:
用代碼來講解:
@Controller
public class UserController {public void say(){System.out.println("hello world");}
}
創建一個UserController類,如果要使用其中的對象就得new UserController(),來實例化對象,而此處我們加上@Controller后就是將對象托管給spring,而我們只需要從Spring中取對象即可,下面講解一下取對象的具體步驟:
@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {ApplicationContext context=SpringApplication.run(DemoApplication.class, args);//1.通過類型取UserController controller=context.getBean(UserController.class);controller.say();//2.通過名字取UserController userController1=(UserController) context.getBean("userController");userController1.say();//3.通過名字和類型雙重查找UserController userController2=context.getBean("userController",UserController.class);userController2.say();}}
之后幾個跟controller差不多
方法注解:
使用場景:
1.想修改第三方的無法修改的類
2.想使用多個對象時
代碼解釋:如此時有個無法修改的第三方類
@AllArgsConstructor//添加一個全參數的構造函數
@NoArgsConstructor//添加一個無參數的構造函數
@Data
public class Student {private String name;private int age;
}
想使用它只能外置一個類:
@Component
public class StudentController {@Beanpublic Student userInfo(){return new Student("zhansan",15);}
}
注意此處的方法注釋@Bean必須和任意一個類注釋一起使用,要先讓spring知道你需要托管.
另外也可以new多個對象,但這里就不能通過類型去取了:
@Component
public class StudentController {@Beanpublic Student userInfo(){return new Student("zhangsan", 20);}@Beanpublic Student userInfo1(){return new Student("lisi", 22);}
}
也可以修改默認名字或者添加復數個名字:
指定掃描路徑
在spring搜索bean位置的時候會根據包的存儲位置存儲
也就是這個,有可能你分的包比較多,讓spring無法搜索到你指定的bean,是可以進行修改的:
@ComponentScan("com.example.dome")