<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          底層源碼分析 Spring 的核心功能和執(zhí)行流程(二)

          共 8457字,需瀏覽 17分鐘

           ·

          2021-07-29 06:59

          談一談你對 IoC 和 DI 的理解

          IoC(Inversion of Control,翻譯為“控制反轉(zhuǎn)”)不是一個具體的技術(shù),而是一種設計思想。與傳統(tǒng)控制流相比,IoC 會顛倒控制流,在傳統(tǒng)的編程中需要開發(fā)者自行創(chuàng)建并銷毀對象,而在 IoC 中會把這些操作交給框架來處理,這樣開發(fā)者就不用關(guān)注具體的實現(xiàn)細節(jié)了,拿來直接用就可以了,這就是控制反轉(zhuǎn)。

          IoC 很好的體現(xiàn)出了面向?qū)ο蟮脑O計法則之一——好萊塢法則:“別找我們,我們找你”。即由 IoC 容器幫對象找到相應的依賴對象并注入,而不是由對象主動去找。

          DI(Dependency Injection,翻譯為“依賴注入”)表示組件間的依賴關(guān)系交由容器在運行期自動生成,也就是說,由容器動態(tài)的將某個依賴關(guān)系注入到組件之中,這樣就能提升組件的重用頻率。通過依賴注入機制,我們只需要通過簡單的配置,就可指定目標需要的資源,完成自身的業(yè)務邏輯,而不需要關(guān)心資源來自哪里、由誰實現(xiàn)等問題。

          Spring IoC 有哪些優(yōu)勢

          1. 使用更方便,拿來即用,無需顯式的創(chuàng)建和銷毀的過程;

          2. 可以很容易提供眾多服務,比如事務管理、消息服務等;

          3. 提供了單例模式的支持;

          4. 提供了 AOP 抽象,利用它很容易實現(xiàn)權(quán)限攔截、運行期監(jiān)控等功能;

          5. 更符合面向?qū)ο蟮脑O計法則;

          6. 低侵入式設計,代碼的污染極低,降低了業(yè)務對象替換的復雜性。

          IoC 的注入方式有哪些

          1. 構(gòu)造方法注入:構(gòu)造方法注入主要是依賴于構(gòu)造方法去實現(xiàn),構(gòu)造方法可以是有參的也可以是無參的,我們平時 new 對象時就是通過類的構(gòu)造方法來創(chuàng)建類對象的,每個類對象默認會有一個無參的構(gòu)造方法,Spring 通過構(gòu)造方法注入

          2. Setter 注入:Setter 方法注入的方式是目前 Spring 主流的注入方式,它可以利用 Java Bean 規(guī)范所定義的 Setter/Getter 方法來完成注入,可讀性和靈活性都很高,它不需要使用聲明式構(gòu)造方法,而是使用 Setter 注入直接設置相關(guān)的值

          3. 接口注入:接口注入方式是比較古老的注入方式,因為它需要被依賴的對象實現(xiàn)不必要的接口,帶有侵入性,因此現(xiàn)在已經(jīng)被完全舍棄了

          談一談你對 AOP 的理解

          AOP(
          Aspect-OrientedProgramming,面向切面編程)可以說是 OOP(Object-Oriented Programing,面向?qū)ο缶幊蹋┑难a充和完善,OOP 引入封裝、繼承和多態(tài)性等概念來建立一種公共對象處理的能力,當我們需要處理公共行為的時候,OOP 就會顯得無能為力,而 AOP 的出現(xiàn)正好解決了這個問題。比如統(tǒng)一的日志處理模塊、授權(quán)驗證模塊等都可以使用 AOP 很輕松的處理。

          Spring AOP 目前提供了三種配置方式

          1. 基于 Java API 的方式

          2. 基于 @AspectJ(Java)注解的方式;

          3. 基于 XML <aop /> 標簽的方式

          基于 Java API 的方式

          此配置方式需要實現(xiàn)相關(guān)的接口,例如 MethodBeforeAdvice 和 AfterReturningAdvice,并且在 XML 配置中定義相應的規(guī)則即可實現(xiàn)。

          我們先來定義一個實體類,代碼如下:

          package org.springframework.beans;





          public class Person {

             public Person findPerson() {

                Person person = new Person(1"JDK");

                System.out.println("findPerson 被執(zhí)行");

                return person;

             }

             public Person() {

             }

             public Person(Integer id, String name) {

                this.id = id;

                this.name = name;

             }

             private Integer id;

             private String name;

             // 忽略 Getter、Setter 方法

          }

          再定義一個 advice 類,用于對攔截方法的調(diào)用之前和調(diào)用之后進行相關(guān)的業(yè)務處理,實現(xiàn)代碼如下:

          import org.springframework.aop.AfterReturningAdvice;

          import org.springframework.aop.MethodBeforeAdvice;



          import java.lang.reflect.Method;



          public class MyAdvice implements MethodBeforeAdviceAfterReturningAdvice {

             @Override

             public void before(Method method, Object[] args, Object target) throws Throwable {

                System.out.println("準備執(zhí)行方法: " + method.getName());

             }



             @Override

             public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {

                System.out.println(method.getName() + " 方法執(zhí)行結(jié)束");

             }
          }

          然后需要在 application.xml 文件中配置相應的攔截規(guī)則,配置如下:

          <!-- 定義 advisor -->

          <bean id="myAdvice" class="org.springframework.advice.MyAdvice"></bean>

          <!-- 配置規(guī)則,攔截方法名稱為 find* -->

          <bean class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">

              <property name="advice" ref="myAdvice"></property>

              <property name="pattern" value="org.springframework.beans.*.find.*"></property>

          </bean>



          <!-- 定義 DefaultAdvisorAutoProxyCreator 使所有的 advisor 配置自動生效 -->

          <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean>

          基于 @AspectJ 注解的方式

          首先需要在項目中添加 aspectjweaver 的 jar 包,配置如下:

          <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->

          <dependency>

              <groupId>org.aspectj</groupId>

              <artifactId>aspectjweaver</artifactId>

              <version>1.9.5</version>

          </dependency>

          此 jar 包來自于 AspectJ,因為 Spring 使用了 AspectJ 提供的一些注解,因此需要添加此 jar 包。之后,我們需要開啟 @AspectJ 的注解,開啟方式有兩種。

          可以在 application.xml 配置如下代碼中開啟 @AspectJ 的注解:

          <aop:aspectj-autoproxy/>

          也可以使用 @EnableAspectJAutoProxy 注解開啟,代碼如下:

          @Configuration

          @EnableAspectJAutoProxy

          public class AppConfig {

          }

          之后我們需要聲明攔截器的類和攔截方法,以及配置相應的攔截規(guī)則,代碼如下:

          import org.aspectj.lang.annotation.After;

          import org.aspectj.lang.annotation.Aspect;

          import org.aspectj.lang.annotation.Before;

          import org.aspectj.lang.annotation.Pointcut;



          @Aspect

          public class MyAspectJ {



             // 配置攔截類 Person

             @Pointcut("execution(* org.springframework.beans.Person.*(..))")

             public void pointCut() {

             }



             @Before("pointCut()")

             public void doBefore() {

                System.out.println("執(zhí)行 doBefore 方法");

             }



             @After("pointCut()")

             public void doAfter() {

                System.out.println("執(zhí)行 doAfter 方法");

          然后我們只需要在 application.xml 配置中添加注解類,配置如下:

          <bean class="org.springframework.advice.MyAspectJ"/>

          基于 XML <aop /> 標簽的方式

          基于 XML 的方式與基于注解的方式類似,只是無需使用注解,把相關(guān)信息配置到 application.xml 中即可,配置如下:

          <!-- 攔截處理類 -->

          <bean id="myPointcut" class="org.springframework.advice.MyPointcut"></bean>

          <aop:config>

              <!-- 攔截規(guī)則配置 -->

              <aop:pointcut id="pointcutConfig"

                              expression="execution(* org.springframework.beans.Person.*(..))"/>


              <!-- 攔截方法配置 -->

              <aop:aspect ref="myPointcut">

                  <aop:before method="doBefore" pointcut-ref="pointcutConfig"/>

                  <aop:after method="doAfter" pointcut-ref="pointcutConfig"/>

              </aop:aspect>

          </aop:config>

          之后,添加一個普通的類來進行攔截業(yè)務的處理,實現(xiàn)代碼如下:

          public class MyPointcut {

             public void doBefore() {

                System.out.println("執(zhí)行 doBefore 方法");

             }

             public void doAfter() {

                System.out.println("執(zhí)行 doAfter 方法");

             }

          }

          Spring AOP 的原理

          Spring AOP 的原理其實很簡單,它其實就是一個動態(tài)代理,我們在調(diào)用 getBean() 方法的時候返回的其實是代理類的實例,而這個代理類在 Spring 中使用的是 JDK Proxy 或 CgLib 實現(xiàn)的,它的核心代碼在 DefaultAopProxyFactory#createAopProxy(...) 中,源碼如下:

          public class DefaultAopProxyFactory implements AopProxyFactorySerializable {



          @Override

          public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {

          if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {

          Class<?> targetClass = config.getTargetClass();

          if (targetClass == null) {

          throw new AopConfigException("TargetSource cannot determine target class: " +

          "Either an interface or a target is required for proxy creation.");

          }

                      // 判斷目標類是否為接口

          if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {

                          // 是接口使用 jdk 的代理

          return new JdkDynamicAopProxy(config);

          }

                      // 其他情況使用 CgLib 代理

          return new ObjenesisCglibAopProxy(config);

          }

          else {

          return new JdkDynamicAopProxy(config);

          }

          }

              // 忽略其他代碼

          }


          瀏覽 31
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  久久99偷拍 | 擦逼视频 | 性爱少妇高手无码 | 91成人免费在线 | 黑人在线 |