冬創(chuàng)網(wǎng)站建設(shè)培訓中心網(wǎng)絡(luò)營銷策劃內(nèi)容
尚硅谷2023最新版Spring6課程_bilibili
1 Spring
【強制】Spring是什么?
1) Spring是一款主流的Java EE輕量級開源框架。
? ? 輕量級:體積很小,且不需要依賴于其他組件。
2) 狹義的Spring。
? ? Spring Framework。
3) 廣義的Spring。
? ? 以Spring Framework為核心的Spring技術(shù)棧。
4) Spring的核心思想。
? ? 提供各種服務(wù),以幫助我們簡化基于POJO的Java應(yīng)用程序開發(fā)。
【強制】Spring模塊組成。
1) Spring Core。
? ? spring-core、spring-beans、spring-context、spring-expression。
2) Spring AOP。
? ? spring-aop、spring-aspects、spring-instrument。
3) Spring Data Access。
? ? spring-jdbc、spring-orm、spring-oxm、spring-jms、spring-tx。
4) Spring Web。
? ? spring-web、spring-webmvc、spring-websocket、spring-webflux。
5) Spring Message。
? ? spring-messaging。
6) Spring Test。
? ? spring-test。
2 Spring IoC
2.1 概念
【強制】IoC。
1) IoC:Inversion of Control,控制反轉(zhuǎn),是一種設(shè)計思想。
2) IoC的理念。
? ? 讓別人為你服務(wù)。原先是由程序員自己來包辦關(guān)于對象的一切,現(xiàn)在讓IoC Service Provider(IoC服務(wù)提供者)來負責。
3) IoC可以給我們帶來什么?
? ? 用一句話來概括就是,IoC是一種可以幫助我們解耦各業(yè)務(wù)對象間依賴關(guān)系的對象綁定方式。
【強制】DI。
1) DI:Dependency Injection,依賴注入。
? ? 和IoC是一回事,只是觀察的角度不同。
2) 依賴注入的實現(xiàn)方式。
? ? 構(gòu)造方法注入、setter方法注入。
【強制】IoC容器。
1) IoC容器是Spring對IoC Service Provider的實現(xiàn)。
? ? IoC Service Provider:IoC服務(wù)提供者,是一個概念。
? ? IoC Service Provider主要負責管理Java對象的實例化和初始化,控制對象與對象之間的依賴關(guān)系。
2) Spring提供了兩種容器類型:BeanFactory和ApplicationContext。
? ? BeanFactory是IoC容器的基本實現(xiàn),提供了 對象創(chuàng)建管理和依賴注入服務(wù) 兩種特性。
? ? ApplicationContext是BeanFactory的子接口,在BeanFactory的基礎(chǔ)上提供了 統(tǒng)一資源加載策略、國際化信息支持、容器內(nèi)事件發(fā)布功能 等高級特性。
? ? 我們開發(fā)人員可以無腦選擇ApplicationContext。
3) ApplicationContext接口的常用實現(xiàn)類。
? ? ClassPathXmlApplicationContext。
? ? FileSystemXmlApplicationContext。
? ? ConfigurableApplicationContext。
? ? WebApplicationContext。
【強制】Bean。
1) IoC容器管理的Java對象稱為Spring Bean。
2) bean的作用域。
? ? singleton:在IoC容器中有且僅有一個實例,默認。
? ? prototype:在IoC容器中可以有多個實例,每次獲取都返回一個新的實例。
? ? request:在一個請求范圍內(nèi)有效。
? ? session:在一個會話范圍內(nèi)有效。
3) bean的生命周期(簡化版本)。
? ? 1. 創(chuàng)建bean。
? ? ? ? 以反射或者CGLIB動態(tài)字節(jié)碼生成方式(默認后者)獲得目標類實例。
? ? ? ? 以BeanWrapper對目標類實例進行包裹,返回BeanWrapper實例。
? ? 2. 給bean設(shè)置屬性(包括Aware相關(guān)依賴)。
? ? 3. 調(diào)用bean的后置處理器-初始化前方法。
? ? ? ? 執(zhí)行自定義的BeanPostProcessor.postProcessBeforeInitialization方法。
? ? 4. 初始化bean。
? ? ? ? 執(zhí)行自定義的init-method。
? ? 5. 調(diào)用bean的后置處理器-初始化后方法。
? ? ? ? 執(zhí)行自定義的BeanPostProcessor.postProcessAfterInitialization方法。
? ? 6. 使用bean。
? ? 7. 銷毀bean。
? ? ? ? 關(guān)閉容器時,執(zhí)行自定義的destory-method。
2.2 實踐
【強制】獲取bean。
1) 配置代碼。
<bean id="myBean" class="com.mypath.MyBean"></bean>
2) Java代碼。
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
// 1.根據(jù)ID獲取bean
MyBean myBean1 = (MyBean)context.getBean("myBean");
// 2.根據(jù)類型獲取bean(要求IoC容器中指定類型的bean有且僅有1個)
MyBean myBean2 = context.getBean(MyBean.class);
// 3.根據(jù)ID和類型獲取bean
MyBean myBean3 = context.getBean("myBean", MyBean.class);
【強制】依賴注入。
1) 構(gòu)造方法注入。
<bean id="student" class="com.mypath.Student"><constructor-arg index="0" value="llxz"></constructor-arg><constructor-arg index="1" ref="dream"></constructor-arg>
</bean>
<bean id="dream" class="com.mypath.Dream"></bean>
2) setter方法注入。
<bean id="student" class="com.mypath.Student"><property name="name" value="llxz"></property><property name="dream" ref="dream"></property>
</bean>
<bean id="dream" class="com.mypath.Dream"></bean>
【強制】自動綁定。
1) 手動綁定。
? ? 使用<constructor-arg>或<property>為bean的屬性注入依賴。
2) 自動綁定,也叫自動裝配。
? ? 通過<bean>的autowire屬性,可以指定采用何種類型的自動綁定模式。
? ? Spring提供了5種自動綁定模式:no、byName、byType、constructor、autodetect。默認為no(手動綁定)。
3) 代碼示例(byName)。
? ? Student.book自動綁定bean book。
class Student {private Book book;public void setBook(Book book) {this.book = book;}
}class Book {
}
<bean id="student" class="com.mypath.Student" autowire="byName"></bean>
<bean id="book" class="com.mypath.Book"></bean>
【推薦】FactoryBean。
1) 簡介。
? ? FactoryBean是Spring提供的一種整合第三方框架的常用機制。配置一個FactoryBean類型的bean,在獲取bean的時候得到的并不是class屬性配置的類的實例,而是getObject()方法的返回值。工廠模式。
2) MyFactoryBean實現(xiàn)FactoryBean接口。
public class MyFactoryBean implements FactoryBean<MyBean> {@Overridepublic MyBean getObject() throws Exception {return new MyBean();}@Overridepublic class<?> getObjectType() {return MyBean.class;}
}
3) 配置bean。
<bean id="myBean" class="com.mypath.MyFactoryBean"></bean>
4) 獲取bean。
ApplicationContext context = new ClassPathXmlApplicationContext("spring-factorybean.xml");
MyBean myBean = (MyBean) context.getBean("myBean");
2.3 基于注解開發(fā)
【強制】開啟組件掃描。
1) 開啟組件掃描。
<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!-- 開啟組件掃描 --><context:component-scan base-package="com.mypath.mypackage"/>
</beans>
2) 組件掃描的目標注解。
? ? component-scan默認掃描的注解類型是@Component。
? ? 在@Component 語義基礎(chǔ)上細化后的@Repository、@Service、@Controller 也同樣可以被component-scan掃描到。
3) 被添加到容器的組件的命名規(guī)則。
? ? component-scan在掃描相關(guān)類定義并將它們添加到容器時,會根據(jù)注解的value屬性來生成beanName。默認的命名規(guī)則是 將類名首字母小寫。
【強制】@Autowired。
1) @Autowired 按照類型匹配進行依賴注入。
? ? 類似于byType類型的自動綁定,但它比byType更加靈活,可以標注在屬性、方法、構(gòu)造方法、構(gòu)造方法參數(shù)上。
2) @Autowired 掃描。
? ? IoC容器需要某種方式來了解哪些對象標注了@Autowired,component-scan對此提供了支持。
3) @Qualifier。
? ? 如果用byType方式同時找到多個同類型的對象實例,可以使用注解@Qualifier 對依賴注入的條件做進一步限定。
? ? @Qualifier 是byName自動綁定的注解版,可以單獨使用,也可以和@Autowired 一起使用。
【強制】@Resource。
1) @Resource 是JDK擴展包提供的注解,更加具有通用性。
? ? 除非是JDK 8,否則需要引入依賴。
<dependency><groupId>jakarta.annotation</groupId><artifactId>jakarta.annotation-api</artifactId><version>2.1.1</version>
</dependency>
2) @Resource 默認byName,未指定name時會使用屬性名作為name。通過name找不到的話會嘗試byType。
3) @Resource 用在屬性、setter方法上。
【強制】全注解開發(fā)。
全注解開發(fā)就是不再使用Spring配置文件了,寫一個配置類來代替配置文件。
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;@Configuration
@ComponentScan("com.mypath.mypackage")
public class MyConfig {
}
3 Spring AOP
3.1 概念
【強制】AOP。
1) AOP:Aspect-Oriented Programming,面向方面編程。
2) AOP可以給我們帶來什么?
? ? 使用AOP,我們可以對類似于日志記錄和安全檢查等系統(tǒng)需求進行模塊化的組織。
3) AOP的實現(xiàn)機制。
? ? AOP的實現(xiàn)機制有動態(tài)代理、動態(tài)字節(jié)碼增強、自定義類加載器、AOL擴展等。
? ? 在Spring AOP中,在目標類實現(xiàn)了一些接口的情況下,使用基于接口的動態(tài)代理技術(shù),否則使用基于類的CGLIB動態(tài)字節(jié)碼增強技術(shù)。
【強制】動態(tài)字節(jié)碼增強。
? ? 通常的class文件都是從Java源代碼文件使用Javac編譯器編譯而成的,但只要符含Java class規(guī)范,我們也可以使用ASM或者CGLIB等Java工具庫,在程序運行期間,動態(tài)構(gòu)建字節(jié)碼的class文件。
? ? 在此前提下,我們可以為需要織入橫切邏輯的模塊類在運行期間,通過動態(tài)字節(jié)碼增強技術(shù),為這些系統(tǒng)模塊類生成相應(yīng)的子類,而將橫切邏輯加到這些子類中,讓應(yīng)用程序在執(zhí)行期間使用的是這些動態(tài)生成的子類,從而達到將橫切邏輯織入系統(tǒng)的目的。
? ? 不過,如果需要擴展的類以及類中的實例方法等聲明為final的話,則無法對其進行子類化的擴展。
? ? Spring AOP在無法采用動態(tài)代理機制進行AOP功能擴展的時候,會使用CGLIB庫的動態(tài)字節(jié)碼增強支持來實現(xiàn)AOP的功能擴展。
【強制】AOP基本概念。
1) Joinpoint。
? ? Jointpoint是可以進行織入操作的系統(tǒng)執(zhí)行點。常見的Joinpoint類型有:方法調(diào)用、方法執(zhí)行、構(gòu)造方法調(diào)用、構(gòu)造方法執(zhí)行、字段設(shè)置、字段獲取、異常處理執(zhí)行、類初始化。
2) Pointcut。
? ? Pointcut是Jointpoint的表述方式。有點兒像引用。
? ? Pointcut的表述方式有:直接指定Joinpoint所在方法名稱、正則表達式、使用特定的Pointcut表述語言。使用得比較普遍的是正則表達式。
3) Advice。
? ? Advice是單一橫切關(guān)注點邏輯的載體,它代表將會織入到Jointpoint的橫切邏輯。如果將Aspect比作OOP中的Class,那么Advice就相當于Class中的Method。
? ? 按照Advice在Joinpoint位置執(zhí)行時機的差異或者完成功能的不同,Advice可以分為:
? ? 1. Before Advice:在Joinpoint指定位置之前執(zhí)行的Advice。
? ? 2. After returning Advice:只有在當前Joinpoint處執(zhí)行流程正常完成后才執(zhí)行。
? ? 3. After throwing Advice:只有在當前Jointpoint處執(zhí)行過程中拋出異常情況下才執(zhí)行。
? ? 4. After Advice:不管Joinpoint處執(zhí)行流程是正常終了還是拋出異常都會執(zhí)行。
? ? 5. Around Advice:對附加其上的Joinpoint進行包裹,可以在Joinpoint之前和之后都指定相應(yīng)的邏輯,甚至于中斷或者忽略Joinpoint處原來程序流程的執(zhí)行。我們常使用的Filter功能就是Around Advice的一種體現(xiàn)。
4) Aspect。
? ? Aspect是對系統(tǒng)中的橫切關(guān)注點邏輯進行模塊化封裝的AOP概念實體。
? ? 通常情況下,Aspect可以包含多個Pointcut以及相關(guān)Advice定義。
5) Weaver。
? ? Weaver是織入器,職責是完成橫切關(guān)注點邏輯到系統(tǒng)的最終織入。
? ? ProxyFactory類是Spring AOP中最通用的織入器。
6) Target。
? ? 符合Pointcut指定的條件,將被織入橫切邏輯的對象。
7) AOP各個概念所處的場景。
3.2 實踐
【強制】動態(tài)代理。
1) 代理模式。
? ? 提供一個代理類,讓我們在調(diào)用目標方法的時候,不再是直接對目標方法進行調(diào)用,而是通過代理類間接調(diào)用。讓不屬于目標方法核心邏輯的代碼從目標方法中剝離出來,即解耦。
2) 動態(tài)代理代碼示例。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;public class Test {public static void main(String[] args) {ProxyFactory factory = new ProxyFactory(new MyInterfaceImpl());MyInterface proxy = (MyInterface) factory.getProxy();proxy.hello("myParam");}
}interface MyInterface {String hello(String s);
}class MyInterfaceImpl implements MyInterface {@Overridepublic String hello(String s) {return "hello world";}
}class ProxyFactory {private Object target;public ProxyFactory(Object target) {this.target = target;}public Object getProxy() {ClassLoader classLoader = target.getClass().getClassLoader();Class<?>[] interfaces = target.getClass().getInterfaces();InvocationHandler invocationHandler = new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object result = null;try {System.out.println("[動態(tài)代理][日志] 方法名: " + method.getName());System.out.println("[動態(tài)代理][日志] 參數(shù)列表:" + Arrays.toString(args));System.out.println("[動態(tài)代理][日志] 開始執(zhí)行");result = method.invoke(target, args);System.out.println("[動態(tài)代理][日志] 返回值:" + result);} catch (Exception e) {System.out.println("[動態(tài)代理][日志] 異常:" + e.getMessage());} finally {System.out.println("[動態(tài)代理][日志] 執(zhí)行完畢");}return result;}};return Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);}
}
【強制】Pointcut表達式。
1)?匹配模式。
????execution、within、this、target、args等。
2)?execution模式表達式格式。
????execution([權(quán)限修飾符]?[返回類型]?[全類名].[方法名]([參數(shù)列表]))
????權(quán)限修飾符、返回類型、全類名、方法名?可以用通配符?*?代替。
????全類名、方法名可以部分匹配,如*Service、get*。
????參數(shù)列表?可以用?..?代替。
【強制】@AspectJ?形式的Advice。
1)?@Before。
2)?@AfterReturning。
3)?@AfterThrowing。
4)?@After。
5)?@Around。
【推薦】@AspectJ?形式的Spring?AOP。
1)?配置文件bean.xml。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:context="http://www.springframework.org/schema/context"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-4.3.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.3.xsd"><!-- 開啟組件掃描 --><context:component-scan base-package="com.mypath"></context:component-scan><!-- 開啟aop自動代理 --><bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"><property name="proxyTargetClass" value="true"></property></bean><!-- 基于Schema的aop自動代理 --><!--<aop:aspectj-autoproxy proxy-target-class="true"/>-->
</beans>
2)?Java代碼。
package com.mypath;import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;public class Test {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");MyTask proxy = (MyTask) context.getBean("myTask");proxy.task1();proxy.tas k2();}
}@Component
class MyTask {public void task1() {System.out.println("task1 執(zhí)行");}public void task2() {System.out.println("task2 執(zhí)行");}
}@Aspect
@Component
class PerformanceTraceAspect {private final Logger logger = Logger.getLogger(PerformanceTraceAspect.class);@Pointcut("execution(public void com.mypath.MyTask.task1()) || execution(public void com.mypath.MyTask.task2())")public void pointcut() {}@Around("pointcut()")public Object performanceTrace(ProceedingJoinPoint joinPoint) throws Throwable {String methodName = joinPoint.getSignature().getName();try {logger.info(methodName + " 開始執(zhí)行");return joinPoint.proceed();} finally {logger.info(methodName + " 執(zhí)行結(jié)束");}}
}
3)?輸出。
[02-13 12:42:20] [INFO] [com.mypath.MyAspect:45] task1 開始執(zhí)行 task1 執(zhí)行 [02-13 12:42:20] [INFO] [com.mypath.MyAspect:48] task1 執(zhí)行結(jié)束 [02-13 12:42:20] [INFO] [com.mypath.MyAspect:45] task2 開始執(zhí)行 task2 執(zhí)行 [02-13 12:42:20] [INFO] [com.mypath.MyAspect:48] task2 執(zhí)行結(jié)束
【推薦】基于Schema的Spring?AOP。
1)?Java代碼。
package com.mypath;import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;public class Test {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");MyTask myTask = (MyTask) context.getBean("myTask");myTask.task();}
}@Component
class MyTask {public void task() {System.out.println("task 執(zhí)行");}
}@Component
class MyAspect {private final Logger logger = Logger.getLogger(MyAspect.class);public void doBefore(JoinPoint joinPoint) {if (logger.isInfoEnabled()) {logger.info("before method[" + joinPoint.getSignature().getName() + "] execution.");}}public void doAfterReturning(JoinPoint joinPoint) {if (logger.isInfoEnabled()) {logger.info("method[" + joinPoint.getSignature().getName() + "] completed successfully.");}}public void doAfterThrowing(RuntimeException e) {logger.error(ExceptionUtils.getFullStackTrace(e));}public void doAfter() {logger.warn("release system resources, etc.");}public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {StopWatch watch = new StopWatch();try {watch.start();return joinPoint.proceed();} finally {watch.stop();if (logger.isInfoEnabled()) {logger.info(watch);}}}
}
2)?配置文件bean.xml。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:context="http://www.springframework.org/schema/context"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-4.3.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.3.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-4.3.xsd"><!-- 開啟組件掃描 --><context:component-scan base-package="com.mypath"></context:component-scan><!-- aop配置 --><aop:config><aop:aspect id="myAspect" ref="myAspect" order="2"><aop:pointcut id="privatePointcut" expression="execution(public void com.mypath.MyTask.task())"/><aop:before pointcut-ref="privatePointcut" method="doBefore"/><aop:after-returning pointcut-ref="privatePointcut" method="doAfterReturning"/><aop:after-throwing pointcut-ref="privatePointcut" method="doAfterThrowing" throwing="e"/><aop:after pointcut-ref="privatePointcut" method="doAfter"/><aop:around pointcut-ref="privatePointcut" method="doAround"/></aop:aspect></aop:config>
</beans>
3)?輸出。
[02-13 13:22:40] [INFO] [com.mypath.MyAspect:33] before method[task] execution. task 執(zhí)行 [02-13 13:22:40] [INFO] [com.mypath.MyAspect:60] StopWatch '': running time = 11056500 ns; [] took 11056500 ns = 100% [02-13 13:22:40] [WARN] [com.mypath.MyAspect:49] release system resources, etc. [02-13 13:22:40] [INFO] [com.mypath.MyAspect:40] method[task] completed successfully.
4 事務(wù)
【推薦】聲明式事務(wù)。
事務(wù)控制的代碼結(jié)構(gòu)基本是確定的,所以框架就可以將固定模式的代碼抽取出來,進行封裝。
通過配置的方式、由框架實現(xiàn)的事務(wù)稱為聲明式事務(wù)。
【推薦】Spring事務(wù)屬性。
1) 只讀。
? ? true/false。
2) 超時。
? ? 超時回滾。單位:秒。
3) 回滾策略。
? ? rollbackFor:回滾。
? ? noRollbackFor:不回滾。
4) 隔離級別。
? ? DEFAULT:使用數(shù)據(jù)庫默認的隔離級別。
? ? READ_UNCOMMITTED:讀未提交。
? ? READ_COMMITTED:讀已提交。
? ? REPEATABLE_READ:可重復讀。
? ? SERIALIZABLE:串行化。
5) 傳播行為。
? ? REQUIRED:支持當前事務(wù),如果當前沒有事務(wù),就新建一個(默認)。
? ? SUPPORTS:支持當前事務(wù),如果當前沒有事務(wù),就以非事務(wù)方式運行。
? ? MANDATORY:如果當前沒有事務(wù),拋出異常。
? ? REQUIRES_NEW:開啟一個新的事務(wù),如果有已存在的事務(wù),將已存在的事務(wù)掛起。
? ? NOT_SUPPORTED:以非事務(wù)方式運行,如果有已存在的事務(wù),將已存在的事務(wù)掛起。
? ? NEVER:以非事務(wù)方式運行,如果有已存在的事務(wù),拋出異常。
? ? NESTED:如果有已存在的事務(wù),則運行在一個嵌套式事務(wù)中。被嵌套的事務(wù)可以獨立于外層事務(wù)進行提交或回滾。
【推薦】事務(wù)的全注解實現(xiàn)。
1) 配置事務(wù)。
import javax.sql.DataSource;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;@Configuration
@ComponentScan("com.mypath")
@EnableTransactionManagement
public class Test {@Beanpublic DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource) {DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();dataSourceTransactionManager.setDataSource(dataSource);return dataSourceTransactionManager;}
}
2) 使用事務(wù)。
使用@Transactional 注解標識類或方法。
5 統(tǒng)一資源加載
開發(fā)中。。
6 其他
6.1 反射
【推薦】反射。
1) 獲取Class對象。
Class clazz1 = MyClass.class;
Class clazz2 = new MyClass().getClass();
Class clazz3 = Class.forName("com.mypath")
2) 獲取構(gòu)造方法。
// 獲取所有的構(gòu)造方法
Constructor[] constructors1 = clazz2.getDeclaredConstructors();
// 獲取所有的public構(gòu)造方法
Constructor[] constructors2 = clazz2.getConstructors();// 帶參數(shù)的構(gòu)造方法, 括號內(nèi)為參數(shù)對應(yīng)的Class對象列表
Constructor constructor = clazz2.getConsturctor(String.class, int.class);
3) MyClass實例化。
// 如果constructor為private構(gòu)造方法
// constructor.setAccessible(true);
MyClass myClass = (MyClass)constructor.newInstance("param1", 2);
4) 獲取屬性。
// 獲取所有的屬性
Field[] fields1 = clazz1.getDeclaredFields();
// 獲取所有的public屬性
Field[] fields2 = clazz1.getFields();
5) 獲取方法。
// 獲取所有的方法
Method[] methods1 = clazz2.getDeclaredMethods();
// 獲取所有的public方法
Method[] methods2 = clazz2.getMethods();
6) 執(zhí)行方法。
// 如果method為private方法
// method.setAccessible(true);
method.invoke("param1", 2);
6.2 Log4j2
【推薦】Log4j2的重要組件。
1) 日志信息的優(yōu)先級。
? ? 日志信息的優(yōu)先級從低到高有:TRACE(追蹤)、DEBUG(調(diào)試)、INFO(信息)、WARN(警告)、FATAL(嚴重錯誤)。
2) 日志信息的輸出目的地。
? ? 將日志打到控制臺或文件。
3) 日志信息的輸出格式。
【推薦】log4j2的使用。
1) 引入依賴。
<dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId><version>2.19.0</version>
</dependency>
<dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-slf4j2-impl</artifactId><version>2.19.0</version>
</dependency>
2) 創(chuàng)建配置文件log4j2.xml。
? ? 省略。
3) 導包。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
4) 初始化Logger對象。
private Logger logger = LoggerFactory.getLogger(MyClass.class);
5) 打印信息。
logger.info("hello world");
6.3 JdbcTemplate
【推薦】JdbcTemplate的使用。
1) 引入依賴。
<!-- Spring JDBC -->
<dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>6.0.2</version>
</dependency>
<!-- Druid數(shù)據(jù)源 -->
<dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.15</version>
</dependency>
<!-- MySQL驅(qū)動 -->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.30</version>
</dependency>
2) 創(chuàng)建配置文件jdbc.properties。
jdbc.user=roo
jdbc.password=root
jdbc.url=jdbc:mysql://localhost:3306/spring?characterEncoding=utf8&useSSL=false
jdbc.driver=com.mysql.cj.jdbc.Driver
3) 創(chuàng)建配置文件bean.xml。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:context="http://www.springframework.org/schema/context"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-4.3.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.3.xsd"><!-- 導入外部屬性文件 --><context:property-placeholder location="classpath:jdbc.properties"/><!-- 配置JDBCTemplate --><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="druidDataSource"/></bean><!-- 配置數(shù)據(jù)源 --><bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="url" value="${jdbc.url}"/><property name="driverClassName" value="${jdbc.driver}"/><property name="username" value="${jdbc.user}"/><property name="password" value="${jdbc.password}"/></bean>
</beans>
4) 創(chuàng)建測試類。
import java.util.List;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;public class Test {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");JdbcTemplate jdbcTemplate = (JdbcTemplate) context.getBean("jdbcTemplate");String insertSql = "INSERT INTO my_table VALUES(?, ?, ?)";Object[] params = { 1, "hello", "world" };jdbcTemplate.update(insertSql, params);String selectSql = "SELECT * FROM my_table";List<Object> list = jdbcTemplate.query(selectSql,new BeanPropertyRowMapper<>(Object.class));System.out.println(list);}
}
【推薦】JdbcTemplate的全注解實現(xiàn)。
import javax.sql.DataSource;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;import com.alibaba.druid.pool.DruidDataSource;@Configuration
@ComponentScan("com.mypath")
public class MySpringConfig {@Bean(name = "jdbcTemplate")public JdbcTemplate getJdbcTemplate(DataSource dataSource) {JdbcTemplate jdbcTemplate = new JdbcTemplate();jdbcTemplate.setDataSource(dataSource);return jdbcTemplate;}@Beanpublic DataSource getDataSource() {DruidDataSource dataSource = new DruidDataSource();dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");dataSource.setUsername("root");dataSource.setPassword("root");dataSource.setUrl("jdbc:mysql://localhost:3306/spring?characterEncoding=utf8&useSSL=false");return dataSource;}
}