關於Spring中的AOP和事物的源碼剖析

首先對spring的原理進行簡單的說明:用過spring的朋友都知道spring的強大和高深,都覺得深不可測,其實當你真正花些時間讀一讀源碼就知道它的一些技術實現其實是建立在一些最基本的技術之上而已;例如AOP(面向方面編程)的實現是建立在CGLib提供的類代理和jdk提供的接口代理,IOC(控制反轉)的實現建立在工廠模式、java反射機制和jdk的操作XML的DOM解析方式,Tansaction(事物)的現實也是建立在CGLib提供的類代理和jdk提供的接口代理。CGLib的底層其實是ASM開源框架,它只是對ASM進行了封裝,讓我們直接以對象的形式操作而非java虛擬機中的字節碼指令。總的來說大的技術實現要靠小得技術支撐,大多數著名的框架說白了是建立在小得技術之上而已。

       下面來對spring源碼中的基本技術進行深入的剖析:先來說說AOP的實現,其實AOP就靠代理模式實現的,如:org.springframework.aop.framework.ProxyFactoryBean,看一下它實現的接口

public class ProxyFactoryBean extends ProxyCreatorSupport implements
  FactoryBean, BeanClassLoaderAware, BeanFactoryAware {


 public Object getObject() throws BeansException {
  initializeAdvisorChain();
  if (isSingleton())//是否是單例的,spring中有單例和多例兩種情況
   return getSingletonInstance();//創建一個單例的代理對象
  if (targetName == null)
   logger
     .warn("Using non-singleton proxies with singleton targets is often undesirable. Enable prototype proxies by setting the 'targetName' property.");
  return newPrototypeInstance();///創建一個多例的代理對象,這是默認情況
 }

其中有一個FactoryBean接口,這個接口中的getObject()方法起着連接作用,在WebApplicationContext調用getBean(String beanName)使用首先調用FactoryBean的getObject()返回一個代理對象實例,在spring的代理應用場所中FactoryBean是必不可少的。

咱們繼續跟蹤:

private synchronized Object newPrototypeInstance() {
  if (logger.isTraceEnabled())
   logger.trace((new StringBuilder(
     "Creating copy of prototype ProxyFactoryBean config: "))
     .append(this).toString());
  ProxyCreatorSupport copy = new ProxyCreatorSupport(getAopProxyFactory());//委託給代理工廠創建代理
  TargetSource targetSource = freshTargetSource();//對被代理對象的封裝
  copy.copyConfigurationFrom(this, targetSource, freshAdvisorChain());
  if (autodetectInterfaces && getProxiedInterfaces().length == 0
    && !isProxyTargetClass())
   copy.setInterfaces(ClassUtils.getAllInterfacesForClass(targetSource
     .getTargetClass(), proxyClassLoader));//設置被代理的接口
  copy.setFrozen(freezeProxy);
  if (logger.isTraceEnabled())
   logger
     .trace((new StringBuilder(
       "Using ProxyCreatorSupport copy: ")).append(copy)
       .toString());
  return getProxy(copy.createAopProxy()); //調用代理工廠創建代理
 }

protected Object getProxy(AopProxy aopProxy) {
  return aopProxy.getProxy(proxyClassLoader);//創建代理對象
 }

下面是ProxyCreatorSupport 的一些方法
public class ProxyCreatorSupport extends AdvisedSupport {

public ProxyCreatorSupport() {
  listeners = new LinkedList();
  active = false;
  aopProxyFactory = new DefaultAopProxyFactory();//默認代理工廠
 }

public AopProxyFactory getAopProxyFactory() {
  return aopProxyFactory;
 }

protected final synchronized AopProxy createAopProxy() {
  if (!active)
   activate();
  return getAopProxyFactory().createAopProxy(this); //代理工廠創建代理
 }

通過以上的跟蹤就知道代理對象是被代理工廠創建的,代理對象對被代理對象進行代理,所以要分析代理對象的創建過程就必須從代理工廠入手,下面我們繼續跟蹤代理工廠DefaultAopProxyFactory。

 


public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {

//CGLib代理工廠
 private static class CglibProxyFactory {

  public static AopProxy createCglibProxy(AdvisedSupport advisedSupport) {
   return new Cglib2AopProxy(advisedSupport);//創建CGbli代理對象
  }

  private CglibProxyFactory() {
  }
 }

 public DefaultAopProxyFactory() {
 }

//代理工廠創建代理對象的具體代碼

 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())//如果被代理對象是現實了接口的話就使用jdk的接口代理模式否則使用CGLib提供的類代理模式
    return new JdkDynamicAopProxy(config);//創建jdk動態代理
   if (!cglibAvailable)
    throw new AopConfigException(
      "Cannot proxy target class because CGLIB2 is not available. Add CGLIB to the class path or specify proxy interfaces.");
   else
    return CglibProxyFactory.createCglibProxy(config);//創建cglib動態代理
  } else {
   return new JdkDynamicAopProxy(config);//創建jdk動態代理
  }
 }

通過上面的代碼分析知道了spring預備了兩種代理模式基於ASM字節碼操作的CGLib提供的類代理和jdk提供的接口代理。下面就對這兩種代理模式再進行深入的剖析:

剖析一JdkDynamicAopProxy源碼:

看一下實現接口InvocationHandler,這是jdk代理中調用處理程序,關於他可以參考其他日誌這裏不再詳細講解。
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler,
  Serializable {

public Object getProxy(ClassLoader classLoader) {
  if (logger.isDebugEnabled())
   logger.debug((new StringBuilder(
     "Creating JDK dynamic proxy: target source is ")).append(
     advised.getTargetSource()).toString());

//這是我們所熟悉的jdk接口代理的一些代碼
  Class proxiedInterfaces[] = AopProxyUtils
    .completeProxiedInterfaces(advised);
  findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
  return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
 }

//這個方法中調用處理程序的invoke方法將會把調用處理委託給方法攔截器MethodInterceptor(也是環繞通知)
public Object invoke(Object proxy, Method method, Object args[])
        throws Throwable
    {

       target = targetSource.getTarget();//被代理對象出現了
        if(target != null)
            targetClass = target.getClass();
        List chain = advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
        if(chain.isEmpty())
        {
            retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);
        } else
        {

          
            MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
            retVal = invocation.proceed();//這裏將調用方法攔截器,具體看下面的代碼
        }

}

public class ReflectiveMethodInvocation implements ProxyMethodInvocation,
  Cloneable {

public Object proceed() throws Throwable {
  if (currentInterceptorIndex == interceptorsAndDynamicMethodMatchers
    .size() - 1)
   return invokeJoinpoint();
  Object interceptorOrInterceptionAdvice = interceptorsAndDynamicMethodMatchers
    .get(++currentInterceptorIndex);
  if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
   InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
   if (dm.methodMatcher.matches(method, targetClass, arguments))
    return dm.interceptor.invoke(this);//方法攔截器被調用
   else
    return proceed();
  } else {
   return ((MethodInterceptor) interceptorOrInterceptionAdvice)
     .invoke(this);//方法攔截器被調用
  }
 }


}

到現在爲止關於代理對象的創建過程的跟蹤已近基本結束除了CGLib,現在總結一下調用路線:ProxyFactoryBean調用AOPProxyFactory創建代理AOPProxy,AOPProxy現實對被代理對象的代理。綜合上面的代碼可以看出spring的代理的原理,其實就是對JDK和CGLib進行封裝和擴展,把他們的InvocationHandler調用處理程序委託給MethodBeforeAdvice(前通知),ReturnAfterAdvice(後通知),MethodInterceptor(環繞通知)。

 

下面我們來剖析一下org.springframework.transaction.interceptor.TransactionProxyFactoryBean。

TransactionProxyFactoryBean是對事物進行控制,具體來說他就是將需要應用事物控制的類進行代理,然後當調用被代理對象的方法時實現方法攔截器的事物攔截器就會檢查該類的方法是否符合事物屬性的規則,如果符合那麼事物攔截器就會調用事物管理器發起事物。下面看一下源代碼來證實一下:


public class TransactionProxyFactoryBean extends
  AbstractSingletonProxyFactoryBean implements BeanFactoryAware {
 private final TransactionInterceptor transactionInterceptor = new TransactionInterceptor();//這是一個實現攔截器的事物攔截器

 public TransactionProxyFactoryBean() {
 }

 public void setTransactionManager(
   PlatformTransactionManager transactionManager) {
  transactionInterceptor.setTransactionManager(transactionManager);//這裏給事物攔截器設置一個事物管理器用於發起事物
 }

 public void setTransactionAttributes(Properties transactionAttributes) {
  transactionInterceptor.setTransactionAttributes(transactionAttributes);//這裏給事物攔截器設置一些事物屬性就是事物的規則用於檢查一個類的方法是否可以進行事物控制
 }

 public void setTransactionAttributeSource(
   TransactionAttributeSource transactionAttributeSource) {
  transactionInterceptor
    .setTransactionAttributeSource(transactionAttributeSource);
 }

我們在看一下他的父類:

實現接口有FactoryBean接口,這個接口上面已經提到過應該有些印象吧。InitializingBean 接口用於初始化工作,在實例化WebApplicationContext之後解析xml時會調用到。
public abstract class AbstractSingletonProxyFactoryBean extends ProxyConfig
  implements FactoryBean, BeanClassLoaderAware, InitializingBean {

//同樣是在WebApplicationContext的getBan()方法調用時調用它來獲取已經創建好的代理對象,這和上面有些不同的是代理對象不是在調用是創建而是在初始化時創建,具體看初始化方法
 public Object getObject() {
  if (proxy == null)
   throw new FactoryBeanNotInitializedException();
  else
   return proxy;
 }

//InitializingBean 接口的初始化方法用於創建代理對象

public void afterPropertiesSet() {
  if (target == null)
   throw new IllegalArgumentException("Property 'target' is required");
  if (target instanceof String)
   throw new IllegalArgumentException(
     "'target' needs to be a bean reference, not a bean name as value");
  if (proxyClassLoader == null)
   proxyClassLoader = ClassUtils.getDefaultClassLoader();
  ProxyFactory proxyFactory = new ProxyFactory();//創建代理工廠
  if (preInterceptors != null) {
   Object aobj[];
   int k = (aobj = preInterceptors).length;
   for (int i = 0; i < k; i++) {
    Object interceptor = aobj[i];
    proxyFactory.addAdvisor(advisorAdapterRegistry
      .wrap(interceptor));//對攔截器進行包裝
   }

  }
  proxyFactory.addAdvisor(advisorAdapterRegistry
    .wrap(createMainInterceptor()));//對攔截器進行包裝
  if (postInterceptors != null) {
   Object aobj1[];
   int l = (aobj1 = postInterceptors).length;
   for (int j = 0; j < l; j++) {
    Object interceptor = aobj1[j];
    proxyFactory.addAdvisor(advisorAdapterRegistry
      .wrap(interceptor));//對攔截器進行包裝
   }

  }
  proxyFactory.copyFrom(this);
  TargetSource targetSource = createTargetSource(target);//包裝被代理對象
  proxyFactory.setTargetSource(targetSource);
  if (proxyInterfaces != null)
   proxyFactory.setInterfaces(proxyInterfaces);//設置被代理對象實現的接口
  else if (!isProxyTargetClass())
   proxyFactory.setInterfaces(ClassUtils.getAllInterfacesForClass(
     targetSource.getTargetClass(), proxyClassLoader));
  proxy = proxyFactory.getProxy(proxyClassLoader);//創建代理對象
 }
}

這裏的代理對象創建過程和上面的基本一樣,就不在囉嗦了有興趣的可以自己去看看。

現在總結一下事物是被事物攔截器所調用和控制的,事物管理器是被事物攔截器調用和控制的,代理就是一種來實現這種事物控制的方式和機制而已。這個AOP類似。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章