文章来源:http://blog.csdn.NET/longyulu/article/details/36174979

用过spring的朋友都知道spring的强大和高深,都觉得深不可测,其实当你真正花些时间读一读源码就知道它的一些技术实现其实是建立在一些最基本的技术之上而已;例如AOP(面向方面编程)的实现是建立在CGLib提供的类代理和jdk提供的接口代理,IOC(控制反转)的实现建立在工厂模式、Java反射机制和jdk的操作XML的DOM解析方式.

       下面来对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类似。

AOP和IOC的实现原理(用到的设计模式)的更多相关文章

  1. springmvc 运行原理 Spring ioc的实现原理 Mybatis工作流程 spring AOP实现原理

    SpringMVC的工作原理图: SpringMVC流程 . 用户发送请求至前端控制器DispatcherServlet. . DispatcherServlet收到请求调用HandlerMappin ...

  2. Spring(二)IOC底层实现原理

    IOC原理 将对象创建交给Spring去管理. 实现IOC的两种方式 IOC配置文件的方式 IOC注解的方式 IOC底层实现原理 底层实现使用的技术 1.1 xml配置文件 1.2 dom4j解析xm ...

  3. AOP和IOC的作用

    IOC:控制反转,是一种设计模式.一层含义是控制权的转移:由传统的在程序中控制依赖转移到由容器来控制:第二层是依赖注入:将相互依赖的对象分离,在spring配置文件中描述他们的依赖关系.他们的依赖关系 ...

  4. AOP和IOC理解

    在百度上看到一篇很有意思的文章,是对AOP的一种解释,如下:(摘自:百度文库的 AOP和IOC最容易理解的说明(Spring知识小计)): IOC,依赖倒置的意思, 所谓依赖,从程序的角度看,就是比如 ...

  5. spring框架的IOC的底层原理

    1.IOC概念:spring容器创建对象并管理 2.IOC的底层原理的具体实现: 1)所使用的技术: (1). dom4j解析xml配置文件 (2).工厂设计模式(解耦合) (3).反射 第一步:配置 ...

  6. IOC的实现原理—反射与工厂模式的结合

    反射机制概念   我们考虑一个场景,如果我们在程序运行时,一个对象想要检视自己所拥有的成员属性,该如何操作?再考虑另一个场景,如果我们想要在运行期获得某个类的Class信息如它的属性.构造方法.一般方 ...

  7. Spring源码学习之IOC容器实现原理(一)-DefaultListableBeanFactory

    从这个继承体系结构图来看,我们可以发现DefaultListableBeanFactory是第一个非抽象类,非接口类.实际IOC容器.所以这篇博客以DefaultListableBeanFactory ...

  8. SpringBoot AOP 与 IoC

    Spring的核心就是AOP与IoC,想要学习SpringBoot,首先得理解这些概念: AOP(Aspect Oriented Programming 面向切面编程) IoC(Inversion o ...

  9. AOP和IOC的作用(转)

    AOP和IOC的作用 转载▼     IOC:控制反转,是一种设计模式.一层含义是控制权的转移:由传统的在程序中控制依赖转移到由容器来控制:第二层是依赖注入:将相互依赖的对象分离,在spring配置文 ...

随机推荐

  1. pyspider 安装时 Could not run curl-config

    sudo aptitude install libcurl4-openssl-dev

  2. 用css实现网站切角效果 使用css3属性:渐变

     都是大量的练习,老师练习乒乓球花了大量时间,十万次一个动作的重复,高中班主任说过,世上没有天才,只是重复的次数多了,自然被认作了天才,小小班的学生之所以厉害是因为他们重复一个知识点次数多,所以没有一 ...

  3. Java中Map常用方法总结以及遍历方式的汇总

    一.整理: 看到array,就要想到角标. 看到link,就要想到first,last. 看到hash,就要想到hashCode,equals. 看到tree,就要想到两个接口.Comparable, ...

  4. pixelmator处理png图片,处理掉过白的留白。

    作为一个CTO,还是得学会一些普通的修图技术的.这不,刚学会在pixelmator下如何处理png中过多的留白. 汗,其实就是一个菜单选项而已./image/trim canvas 效果如下:

  5. Integer.toBinaryString()的源代码解析

    private static String toUnsignedString(int i, int shift) { char[] buf = new char[32];//i是要整形,这里得把它化成 ...

  6. Android 解析Json_fastJson

    FastJSON是一个很好的java开源json工具类库,相比其他同类的json类库,它的速度的确是fast,最快!但是文档做得不好,在应用前不得不亲测一些功能.   实际上其他的json处理工具都和 ...

  7. 去掉tableview顶部留白

    self.automaticallyAdjustsScrollViewInsets = NO;   //去掉tableVIew顶部留白

  8. Java实现归并排序

    package Sort; import java.util.Arrays; public class MergeSort { public static void merge(int[] list, ...

  9. iOS,几种设计模式

    1.单例模式 2.观察者模式 3.委托代理 4.block回调 5.反射机制 单例模式 iOS单例模式的2种方式.根据线程安全的实现来区分,一种是使用@synchronized ,另一种是使用GCD的 ...

  10. String转json

    一.下载json 具体到http://www.json.org/上找Java-json下载,并把其放到项目源代码中,这样就可以引用其类对象了 转载地址:http://blog.csdn.net/tax ...