1. 程式人生 > >【spring源碼學習】spring的AOP面向切面編程的實現解析

【spring源碼學習】spring的AOP面向切面編程的實現解析

內部 遠程調用 關註 add aps 文件 uem 連接 row

一:Advice(通知)
(1)定義在連接點做什麽,為切面增強提供織入接口。在spring aop中主要描述圍繞方法調用而註入的切面行為。
(2)spring定義了幾個時刻織入增強行為的接口
??=>org.springframework.aop.BeforeAdvice
???org.springframework.aop.MethodBeforeAdvice
??=>org.springframework.aop.AfterAdvice
???org.springframework.aop.AfterReturningAdvice
??=>org.springframework.aop.ThrowsAdvice

二:PointCut(切點)
(1)決定Advice應該作用那些連接點。也就是說通過PointCut來定義需要增強的方法集合。
(2)spring定義的PointCut的接口
??=>org.springframework.aop.Pointcut
??=>org.springframework.aop.TruePointcut
??=> org.springframework.aop.support.JdkRegexpMethodPointcut
(3)相關接口。PointCut接口會返回兩個對象,一個ClassFilter,一個是MethodMatcher
??=>org.springframework.aop.ClassFilter
??=>org.springframework.aop.TrueClassFilter

??=>org.springframework.aop.MethodMatcher 匹配當前方法是否需要執行增強邏輯,也就是是否需要執行Advice接口的方法。
??=>org.springframework.aop.TrueMethodMatcher

三:通知器皿(Advisor)
??(1)完成對目標方法的切面增強設計(advice)和關註點的設計(PoinCut)以後,需要一個對象把他們結合起來,完成這個作用的就是(Advisor)
??(2)spring定義的Advisor接口
??=>org.springframework.aop.Advisor
??=>org.springframework.aop.support.DefaultPointcutAdvisor

??(3)Advisor的控制器的接口
??=>org.springframework.aop.framework.adapter.AdvisorAdapter
??=>org.springframework.aop.framework.adapter.AfterReturningAdviceAdapter 目標方法執行完執行該增強的控制器
??=>org.springframework.aop.framework.adapter.MethodBeforeAdviceAdapter 目標方法未執行前執行該增強的控制器
??=>org.springframework.aop.framework.adapter.ThrowsAdviceAdapter 目標方法執行過程拋出異常執行該增強的控制器

四:springAop的相關
??(1)springAop的核心技術是動態代理。動態代理的技術是jdk的一個特征。
??(2)springAop的代理對象生成案例
????=>org.springframework.aop.framework.ProxyFactoryBean
????=>org.springframework.aop.framework.ProxyFactory


五:ProxyFactoryBean的工作流程。
(1)實現FactoryBean接口的類,在想IOC容器申請bean的時候,其實返回的是該類執行getObject()方法的返回。
(2)ProxyFactoryBean的getObject()方法返回的是目標對象的代理對象。
??其執行過程
??=>根據配置的interceptorNames的屬性值先初始化代理增強的鏈子.根據interceptorNames從IOC容器中得到增強類的bean,然後判斷其類型,形成DefaultPointcutAdvisor對象。
??=>根據配置的targetName屬性值從IOC容器中得到目標對象的bean,形成一個SingletonTargetSource對象。
??=>將其本身作為一個aop代理對象創建的數據配置類,創建一個動態代理對象,返回給ioc容器申請。
(3)在執行目標對象的方法過程中,會根據執行的方法的對象,從代理鏈子裏找到所有的Advisor對象,然後利用其屬性Pointcut對象獲取ClassFilter, MethodMatcher來判斷當前Advisor是否要執行。如果執行,則加入執行代理鏈子中。以jdk動態代理為例子,是org.springframework.aop.framework.JdkDynamicAopProxy類中invoke(Object proxy, Method method, Object[] args)方法中這句代碼List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);。該句代碼中this.advised其實就是ProxyFactoryBean本身。

六案例

一:Advice的對象

技術分享
package com.mobile.thinks.aop.advice;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;

public class LoginBeforeAdvice implements MethodBeforeAdvice{

    @Override
    public void before(Method method, Object[] args, Object target)throws Throwable {
        System.out.println(
"LoginBeforeAdvice.before()執行方法為==>"+method.getName()); System.out.println("LoginBeforeAdvice.before()執行參數為==>"+args); System.out.println("LoginBeforeAdvice.before()執行的目標為==>"+target.getClass()); } }
View Code

二:目標對象

技術分享
package com.mobile.thinks.service.impl;

import java.util.Date; import org.springframework.stereotype.Service; import com.mobile.thinks.entity.User; import com.mobile.thinks.service.UserInfoService; @Service(value="userInfoServiceImpl") public class UserInfoServiceImpl implements UserInfoService{ @Override public User loginByUserNameAndPassWord(String userName, String passWord) { User user=new User(); user.setAddress("三門峽"); user.setAge(28); user.setCreateTime(new Date()); user.setName(userName); return user; } }
View Code

三:配置文件

技術分享
 <!-- 測試ProxyFactoryBean -->
       <!--定義一個advice  -->
       <bean name="loginBeforeAdvice" class="com.mobile.thinks.aop.advice.LoginBeforeAdvice" />
    <!-- 定義FactoryBean -->
    <bean name="userInfoService" class="org.springframework.aop.framework.ProxyFactoryBean">
        <!-- 要代理的目標對象,在ioc容器中的名字 -->
        <property name="targetName">
            <value>userInfoServiceImpl</value>
        </property>
        <!-- 要植入增強功能的advice在IOC容器中的名字 -->
        <property name="interceptorNames">
            <list><value>loginBeforeAdvice</value></list>
        </property>
    </bean>
View Code

七:spring內部基於該中方式實現動態代理的案例。spring提供的HttpInvoker遠程調用.可以閱讀該類getObject方法。實現對Facade接口代理

org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean

【spring源碼學習】spring的AOP面向切面編程的實現解析