微服務 · 如何解決鏈路追蹤問題
阿新 • • 發佈:2020-11-05
spring七大模組
IoC、DI
控制反轉(ioc):是一種思想,建立物件的控制權,從程式程式碼轉移到了ioc容器。
依賴注入(di):是控制反轉的實現方法,bean物件的建立依賴於容器,bean物件中所有的屬性由容器注入。
IoC的實現:採用XML配置 / 使用註解
依賴注入的方式
1.構造器注入,【在配置檔案載入的時候,容器中管理的物件就已經建立了】
<!--1.下標賦值--> <bean id="id_name" class="全類名"> <construct-arg index="0" value="xx"/> <construct-arg index="1" value="xxx"/> </bean> <!--2.型別賦值,不推薦使用,當多個引數型別相同時 會報錯--> <bean id="id_name" class="全類名"> <construct-arg type="java.lang.String" value="xx"/> </bean> <!--3.引數名賦值--> <bean id="id_name" class="全類名"> <construct-arg name="name" value="xx"/> </bean>
2.set注入,常用
<!--1.普通注入--> <bean id="id_name" class="全類名"> <property name="name" value="xx"/> </bean> <!--2.bean注入--> <bean id="id_name" class="全類名"> <property name="name" ref="bean_id"/> </bean> <!--3.陣列--> <bean id="id_name" class="全類名"> <property name="name"> <array> <value>xx</value> <value>xxx</value> </array> </property> </bean> <!--4.list--> <bean id="id_name" class="全類名"> <property name="name"> <list> <value>xx</value> <value>xxx</value> </list> </property> </bean> <!--5.set--> <bean id="id_name" class="全類名"> <property name="name"> <set> <value>xx</value> <value>xxx</value> </set> </property> </bean> <!--6.map--> <bean id="id_name" class="全類名"> <property name="name"> <map> <entry key="x" value="xx"/> </map> </property> </bean> <!--7.空值注入--> <bean> <property> <null/> </property> </bean> <!--properties--> <bean> <property> <pros> <prop key="x">xx</prop> <prop key="xx">xxx</prop> </pros> </property> </bean>
3.介面注入(spring不支援)
bean的作用域
Scope | Description |
---|---|
singleton | 容器中只有一個bean的例項 |
prototype | 每次從容器中獲取bean時,都會產生一個新的例項 |
request | 每次http請求都會建立一個新物件 |
session | 同一個會話共享一個例項,不同的會話使用不同的例項 |
global-session | 所有會話共享同一個例項 |
singleton:單例,一個類只有一個例項。【spring預設作用域】
prototype:原型,每次從容器中獲取物件的時候都會產生一個新物件。
其餘三個只能在web開發中使用。
bean的自動裝配
xml實現在自動裝配:autowired = "byName / byType"
-
byName自動裝配:保證bean的id唯一
-
byType自動裝配:保證bean的class唯一
使用註解實現自動裝配:
- @Autowired; 【最常用】
- 欄位上
- set方法上
- 構造方法上
- 如果@Autowired自動裝配的環境比較複雜(bean的id 不唯一,類中有多個相同的屬性),可以使用@Qulifier(value="xx")配合@Autowired,指定一個唯一的bean物件注入。
- @Resource(name="xx");【功能更強大】
@Autowired和@Resource的區別:
- 都是用來實現自動裝配的,都可以放在屬性上
- @Autowired通過byType實現,如果xml中有多個相同型別的bean,就會注入失敗,報空指標異常
- @Resource通過byName實現,如果找不到對應的bean的id,就通過byType實現!如果xml中有多個相同型別的bean,就會注入失敗,報bean不唯一異常
@Component有三個衍生註解
對應三成架構中的每一層
- Dao【@Repository】
- Service【@Service】
- Controller【@Controller】
這四個註解的功能都是一樣的,為當前類註冊bean物件,交給spring容器管理
三層架構和MVC的區別
AOP是一種技術
提取並封裝跟核心業務無關的重複程式碼。在需要呼叫的時候,使用動態代理技術,在不修改原始碼的基礎上對方法進行增強。比如:許可權管理、事務處理、日誌記錄。
代理模式:靜態代理,動態代理
靜態代理
角色分析:
- 抽象角色:一般使用介面或者抽象類
- 具體角色:被代理的角色
- 代理角色:代理真實角色,相當於中間商,代理後會做一些附屬操作
- 客戶:訪問代理物件的人
好處:
- 使具體角色的操作更純粹!不用再去關注一些公共的業務
- 公共的業務交給代理角色,實現了業務的分工
- 公共業務集中管理,需要擴充套件功能時候更加方便
缺:
- 一個真實角色就會產生一個代理角色,程式碼量翻倍==開發效率變低
動態代理
- 角色和靜態代理角色一樣
- 動態代理的代理類是動態生成的,不是我們寫好的!
- 動態代理分為兩大類:
- 基於介面:JDK動態代理
- 基於子類:cglib代理
需要了解兩個類:Proxy(用於生成代理類),InvocationHandler(介面,呼叫處理程式)
JDK動態代理好處:
- 有靜態代理的所有優點
- 一個動態代理代理的是一個介面,對應一類業務
- 一個動態代理可以代理多個類,只要這些類實現了同一個介面
缺:
- 只會增強最先呼叫的方法,內部之間相互呼叫的方法,是不會被增強的。【這在基於子類和基於介面的動態代理方法中都存在。】
AOP的實現方式
-
使用spring的API
<?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:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!--註冊bean--> <bean id="afterLog" class="proxy.AfterLog"></bean> <bean id="beforeLog" class="proxy.BeforeLog"></bean> <bean id="user2" class="proxy.User"></bean> <!--配置aop,需要匯入aop的約束--> <aop:config> <aop:pointcut id="pointcut" expression="execution(* proxy.User.*(..))"/> <!--執行增強--> <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/> <aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut"/> </aop:config> </beans>
-
自定義切面(是一個類)來實現aop
<?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:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!--註冊bean--> <bean id="user2" class="proxy.User"></bean> <!--自定義切面--> <bean id="aspect" class="proxy.DiyLog"/> <aop:config> <aop:aspect ref="aspect"> <!--切入點--> <aop:pointcut id="point" expression="execution(* proxy.User.*(..))"/> <!--通知--> <aop:before method="before" pointcut-ref="point"/> <aop:after method="after" pointcut-ref="point"/> </aop:aspect> </aop:config> </beans>
-
使用註解實現
<!-- 方式三,使用註解實現--> <bean id="annotationPointCut" class="proxy.DiyLog"/> <!-- 開啟註解支援--> <aop:aspectj-autoproxy/> package proxy; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; //自定義切面,是一個類 @Aspect //表明當前類是一個切面 public class DiyLog { @Before("execution(* proxy.User.*(..))") public void before(){ System.out.println("======方法執行前======="); } @After("execution(* proxy.User.*(..))") public void after(){ System.out.println("======方法執行後======="); } }
spring中的事務管理
- 宣告式事務
- 程式設計式事務(不使用)
配置宣告式事務
<!--配置 事務管理器-->
<bean id="dataSourceTransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--配置事務通知-->
<tx:advice id="txAdvice"
transaction-manager="dataSourceTransactionManager">
<!--給哪些方法配置事務-->
<tx:attributes>
<tx:method name="add*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!--配置aop-->
為什麼需要事務:
如果不配置事務,可能存在資料提交不一致的情況,涉及到資料的一致性和完整性問題。