-
Spring定義一個Bean有哪些方法?依賴注入有哪些方法?
(1)定義Bean的方法
-
注解定義Bean,@Component
用于標記一個類作為Spring的bean。當一個類被@Component注解標記時,Spring會將其實例化為一個bean,并將其添加到Spring容器中。
-
配置文件定義Bean
(2)依賴注入的方法
- 字段(Field):最直接地在類的字段上使用。
public class MyClass {@Autowiredprivate MyDependency myDependency; }
- 構造器(Constructor):在構造器上使用,用于構造器注入。
public class MyClass {private MyDependency myDependency;@Autowiredpublic MyClass(MyDependency myDependency) {this.myDependency = myDependency;} }
- 方法(Method):也可以在一個方法上使用,通常是一個 setter 方法。
public class MyClass {private MyDependency myDependency;@Autowiredpublic void setMyDependency(MyDependency myDependency) {this.myDependency = myDependency;} }
-
-
介紹IOC、AOP、反射
(1)IOC
? Spring IOC容器通過
? ①封裝對象的創建(將對象的創建過程交給Spring管理,從而實現了控制反轉)和生命周期管理(管理對象的初始化和銷毀過程),
? ②使用依賴注入來解耦對象之間的依賴關系(通過 Spring 容器將類 A 所依賴的 B 的實例注入到 A 中,這樣 A 和 B 不再直接依賴,而是通過容器來提供),
? ③利用反射和配置元數據動態地創建和管理對象(當 Spring 容器啟動時,它會根據配置文件或注解(元數據)掃描類的信息,通過反射技術實例化對象,而不需要編寫具體的
new
代碼。反射讓 Spring 能夠動態地操作類的構造函數、方法等),? ④同時提供作用域管理功能(對象的生命周期和可見性范圍。Spring 提供了多種作用域,容器會根據作用域來管理對象的實例化、銷毀等過程。Singleton(單例)、Prototype(原型)、Request、Session、Application 等作用域)。
(2)AOP
? 面向切面編程,AOP能夠將那些與業務無關,卻為業務模塊所共同調用的邏輯(例如事務處理、日志管理、權限控制等)封裝起來,以減少系統的重復代碼,降低模塊間的耦合度。
? 兩個例子:權限校驗攔截器、動態切換數據源。
? Spring AOP的實現依賴于動態代理技術。動態代理是在運行時動態生成代理對象,而不是在編譯時。
注解 @Aspect 用于定義切面,標注在切面類上。 @Pointcut 定義切點,標注在方法上,用于指定連接點。 @Before 在方法執行之前執行通知。 @After 在方法執行之后執行通知。 @Around 在方法執行前后都執行通知。 (3)反射
? 允許在運行時動態地查詢和操作類、方法、字段等信息,并且能夠通過反射來調用類中的方法或修改類的屬性。反射機制的核心原理是:通過
Class
類來獲取類的結構信息,并且使用這些信息在運行時動態地操作類的對象。IOC、DI、動態代理就是用到了反射。①獲取class對象:可以通過類的
Class
對象來訪問類的信息。Class<?> clazz = Class.forName("Person"); //括號里的內容可以是程序運行時才輸入的內容
②查詢類的結構信息:通過
Class
對象,可以獲取類的構造方法、方法、字段、接口、父類等信息。Method[] methods = clazz.getMethods(); // 獲取所有公共方法 Field[] fields = clazz.getFields(); // 獲取所有公共字段 Constructor[] constructors = clazz.getConstructors(); // 獲取所有公共構造函數
③動態創建對象
Constructor<?> constructor = clazz.getConstructor(); // 獲取無參構造 Object instance = constructor.newInstance(); // 使用構造函數創建對象實例
④調用方法
Method method = clazz.getDeclaredMethod("myMethod", String.class); method.setAccessible(true); // 如果是私有方法,需要設置訪問權限 method.invoke(obj, "parameter"); // 調用方法
-
介紹動態代理、靜態代理?
? 代理模式是設計模式中的一種,它通過提供代理對象來控制對原對象的訪問。代理對象充當中介,通常在請求實際操作之前或之后做一些額外的工作(例如檢查權限、緩存結果、延遲加載等)。
? 控制訪問:代理可以控制對實際對象的訪問,增加額外的功能(如安全性、權限管理、日志記錄等)。
? 延遲加載:通過代理,可以延遲初始化或執行耗時的操作,直到真正需要時才執行。
? 性能優化:代理對象可以緩存結果,減少重復計算或請求,提高性能。
? 增強功能:代理對象可以在不修改原對象代碼的情況下,為其增加新的功能,如事務管理、日志記錄等。
(1)動態代理
動態代理是在運行時創建代理對象,代理對象在運行時被動態地生成,因此不需要在編譯時就確定代理類。Java 提供了兩種方式來實現動態代理:
- JDK 動態代理
- 通過
java.lang.reflect.Proxy
類和InvocationHandler
接口動態生成代理類。JDK 動態代理要求目標類實現一個接口。
- 通過
- CGLIB(Code Generation Library)代理
- 通過字節碼生成技術,動態創建目標類的子類來實現代理。CGLIB 代理不要求目標類實現接口,而是通過繼承目標類來實現代理。
(2)靜態代理
? 代理類是在編譯時就已經寫好并且確定的。是由開發者手動編寫的,并且在程序運行之前就已經存在。例如,你在編寫代碼時就知道你需要一個
Proxy
類,它會代理RealSubject
類的方法。在靜態代理中,代理類和目標類的關系是固定的,編譯時就已經確定。? 代理模式是JAVA的一種設計模式,而AOP是Spring框架中的一個特性,是使用了動態代理來實現的。
- JDK 動態代理
-
Spring的循環依賴的原因以及解決方法;(眾安)
循環依賴指的是兩個類中的屬性相互依賴對方:例如 A 類中有 B 屬性,B 類中有 A屬性,從而形成了一個依賴閉環。
Spring中的循環依賴問題有三種情況:
- 第一種:通過構造方法進行依賴注入時產生的循環依賴問題。
- 第二種:通過setter方法進行依賴注入且是在多例(原型)模式下產生的循環依賴問題。
- 第三種:通過setter方法進行依賴注入且是在單例模式下產生的循環依賴問題。
單例模式適用于全局唯一的資源管理,如配置管理、日志記錄、數據庫連接池等。它的特點是保證類在全局范圍內只有一個實例,所有地方都使用同一個對象。
多例模式適用于需要多個獨立實例的場景,如用戶會話、任務調度、訂單管理等。每個實例有自己的狀態和行為,不共享數據。
只有【第三種方式】的循環依賴問題被 Spring 解決了,其他兩種方式在遇到循環依賴問題時,Spring都會產生異常。
(1)Spring實例化Bean:Spring嘗試創建A的實例,發現A依賴B,因此需要實例化B。Spring在創建B時,發現B依賴A,但此時A還沒有完成初始化,所以Spring會創建A的空對象并將其放入
singletonObjects
一級緩存中并開始創建B。(3)循環依賴暴露
- 當Spring嘗試創建B時,由于A還沒有完全初始化,Spring會把A實例(未完全初始化)提前暴露到
earlySingletonObjects
二級緩存中,這時A成為一個半初始化的Bean。 - B可以通過
earlySingletonObjects
二級緩存獲得這個提前暴露的A對象,從而完成B的依賴注入。
(3)初始化Bean
-
依賴注入完成后,Spring繼續初始化B(如調用
@PostConstruct
等),然后將B放入三級singletonFactories
緩存中,表示B已經完全初始化。 -
Spring繼續完成A的初始化工作,注入B,完成生命周期的其他部分,并將A放入三級
singletonFactories
緩存中,表示A也已經完全初始化。
(4)總結
- 在依賴注入過程中,Spring通過
earlySingletonObjects
二級緩存提供了B對A的依賴,通過singletonFactories
三級緩存提供了A對B的依賴,從而打破了循環依賴。
-
列舉幾個Spring常用的注解?(美團)
注解 作用 @Autowired 自動裝配bean,當Spring容器中存在與要注入的屬性類型匹配的bean時,它會自動將bean注入到屬性中 @Component Spring會將一個類實例化為一個bean,并將其添加到Spring容器中。 @Configuration 用于標記一個類作為Spring的配置類,配置類可以包含@Bean注解的方法,用于定義和配置bean,作為全局配置。 @Bean 用于標記一個方法作為Spring的bean工廠方法,當一個方法被@Bean注解標記時,Spring會將該方法的返回值作為一個bean,并將其添加到Spring容器中 @Service 用于標記服務層的bean,是@Component注解的特例,一般標記在業務service的實現類。 @Repository 用于標記數據訪問層的bean,它也是@Component注解的特例。 @Controller 用于標記控制層的bean,它也是@Component注解的特例。 -
spring、springboot、SpringMVC的區別及關系?(康泰)
Spring 是一個全面的應用開發框架,提供了全面的基礎設施和功能支持。
Spring MVC 是 Spring 框架中的一個模塊,專門用于 Web 開發,采用 MVC 模式來處理 Web 請求和響應。它依賴于 Spring 框架的核心功能,如 IoC 和 AOP。
Spring Boot 是一個基于 Spring 的項目,它封裝了 Spring 和其他相關技術(如 Spring MVC、Spring Data、Spring Security 等),提供自動配置、快速項目啟動器、內嵌服務器三大功能,使開發者能夠快速啟動和構建 Spring 應用。
- 自動配置
- 快速項目啟動器,通過引入不同的 Starter,可以快速集成常用的框架和庫(如數據庫、消息隊列、Web 開發等),極大地提高了開發效率。
- 內嵌服務器(Tomcat、Jetty、Undertow),無需額外配置,即可將應用打包成可執行的 JAR 文件,方便部署和運行。
Spring+Spring MVC = Spring Boot
-
springboot的自動配置原理?(美團、得物)springBoot啟動機制,啟動之后做了哪些步驟?(B站)
-
SpringBoot重要注解
@SpringBootApplication 用于標注主應用程序類,標識一個Spring Boot應用程序的入口點,同時啟用自動配置和組件掃描。 @Controller 標識控制器類,處理HTTP請求。 @RestController 結合@Controller和@ResponseBody,返回RESTful風格的數據。 @Service 標識服務類,通常用于標記業務邏輯層。 @Repository 標識數據訪問組件,通常用于標記數據訪問層。 @Component 通用的Spring組件注解,表示一個受Spring管理的組件。 @Autowired 用于自動裝配Spring Bean。 @Value 用于注入配置屬性值。 @RequestMapping 用于映射HTTP請求路徑到Controller的處理方法。 @GetMapping、@PostMapping、@PutMapping、@DeleteMapping 簡化@RequestMapping的GET、POST、PUT和DELETE請求。 @Configuration 用于指定一個類為配置類,其中定義的bean會被Spring容器管理。 -
怎么用原生的MyBatis去查詢?
(1)配置MyBatis: 在配置文件中配置數據源、MyBatis的Mapper文件位置等信息。
(2)創建實體類:創建與數據庫表對應的實體類,字段名和類型需與數據庫表保持一致。
public class User {private Long id;private String username,private String email,// Getters and setters }
(3)編寫SQL映射文件:在resources目錄下創建XML文件,定義SQL語句和映射關系。
<mapper namespace="com.example.dao.UserMapper"><select id="selectUserById" resultType="com.example.model.User">SELECT * FROM users WHERE id = #{id}</select> </mapper>
(4)編寫DAO接口:創建DAO接口,定義查詢方法。
public interface UserMapper {User selectUserById(Long id); }
(5)編寫具體的SQL查詢語句:在XML文件中編寫對應的SQL語句。
(6)調用查詢方法:在服務層或控制層中調用DAO接口中的方法進行查詢。
// 在Service層中調用 User user = userMapper.selectUserById(1);
-
MyBatis里的 # 和 $ 的區別?
-
Mybatis 在處理 #{}時,會創建預編譯的 SQL 語句,將 SQL 中的 #{} 替換為?號,在執行 SQL 時會為預編譯 SQL 中的占位符(?)賦值,調用 PreparedStatement 的 set 方法來賦值,預編譯的 SQL 語句執行效率高,并且可以防止SQL注入,提供更高的安全性,適合傳遞參數值。
-
Mybatis 在處理 ${} 時,只是創建普通的 SQL語句,然后在執行 SQL語句時 MvBatis 將參數直接拼入到 SQL里,不能防止 SQL注入,因為參數直接拼接到 SQL語句中,如果參數未經過驗證、過濾,可能會導致安全問題。
比如:
<select id="getUserByUsername" resultType="User">SELECT * FROM users WHERE username = '${username}' </select>
在這個查詢中,
${username}
會直接被傳入的username
值替換,假如傳入的username
是惡意的,例如"' OR 1=1"
,查詢語句就變成了:SELECT * FROM users WHERE username = '' OR 1=1
這就是典型的 SQL 注入,因為
$
直接拼接了參數值,導致不安全的 SQL 被執行。大多數情況下都應該使用
#
,特別是涉及到用戶輸入的值時。它可以安全地處理用戶輸入,避免 SQL 注入。只有在確實需要拼接動態 SQL 的結構部分(如表名、列名)時,才應該使用$
。
-
MybatisPlus和Mybatis的區別?(百度)
MybatisPlus是一個基于MyBatis的增強工具庫。
- CRUD操作:MybatisPlus通過繼承BaseMapper接口,提供了一系列內置的快捷方法,使得CRUD操作更加簡單,無需編寫重復的SQL語句。
- 代碼生成器:MvbatisPlus提供了代碼生成器功能,可以根據數據庫表結構自動生成實體類、Mapper接口以及XML映射文件,減少了手動編寫的工作量。
- 通用方法封裝:MybatisPlus封裝了許多常用的方法,如條件構造器、排序、分頁查詢等,簡化了開發過程,提高了開發效率。
- 分頁插件:MybatisPlus內置了分頁插件,支持各種數據庫的分頁查詢,開發者可以輕松實現分頁功能,而在傳統的MyBatis中,需要開發者自己手動實現分頁邏輯。
- 多租戶支持:MvbatisPlus提供了多租戶的支持,可以輕松實現多租戶數據隔離的功能。
- 注解支持:MvbatisPlus引入了更多的注解支持,使得開發者可以通過注解來配置實體與數據庫表之間的映射關系,減少了XML配置文件的編寫。