通过ProxyFactoryBean创建proxy代理类源码分析

Spring 实现Aop除了自己的实现方式外,还封装了AspectJ供我们使用,这里主要是对Spring自身Aop实现的源码做下解析,而这两种方式之间的区别主要在于实现方式和作用时机上:

  • Spring Aop 虽然底层也是通过字节码技术,但是是通过AopProxy生成新的的代理类,在运行时进行类加载,拦截代理对象的调用来实现切面增强。
  • AspectJ 是通过字节码技术在原class对象里插入切面字节码,不产生新类,并且支持在编译期将切面功能插入到class文件里(需要引入AspectJ的编译器)。 至于AspectJ的更多介绍可以看这里
Aop源码解析:

这里主要是通过ProxyFactoryBean作为切入点来看下Aop的实现思路。先列几个概念:

  • advice:切面,用来封装在切入点上 增强的逻辑,比如写日志功能,校验功能
  • pointCut::切入点,用来描述需要在哪里织入切面的增强逻辑。
  • advisor: 将切面和切入点封装起来的类
  • target:需要代理的目标类

了解这几个概念后,开始上代码,根据上面说的几个概念,我们需要创建一个target、一个advice,而advisor和pointCut是由Spring框架已经提供给我们了,我们只需要配置下就可以。
target类:

public class Target {
   public void method1(){
       System.out.println(">>> method1...");
   }
}

advice切面类,根据你的需要的切面类型来实现不同的接口,比如前置增强(在方法前插入增强逻辑)需要实现MethodBeforeAdvice接口,后置增强逻辑需要实现AfterReturningAdvice接口,此处以MethodBeforeAdvice为例:

public class AopAdviceTest implements MethodBeforeAdvice {
  @Override
  public void before(Method method, Object[] objects, Object o) throws Throwable {
      System.out.println(" before ...");
  }
}

Spring的xml配置

<!--定义切面advise-->
<bean id="aopAdviceTest" class="com.alibaba.dubbo.demo.provider.AopAdviceTest"/>
<!--需要代理的对象target-->
<bean id="target" class="com.alibaba.dubbo.demo.provider.Target"/>
<!--定义advisor-->
<bean id="aopAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
        <property name="advice" ref="aopAdviceTest"/>
        <property name="patterns" value=".*method1.*"/>
</bean>

<bean id="aspectTargetProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="target" ref="target"/>
        <property name="interceptorNames">
            <list>
                <value>aopAdvisor</value>
            </list>
        </property>
</bean>   
      

main方法里启动spring容器并获取bean,执行方法:

   public static void main(String[] args) throws Exception {
        System.out.println("服务启动成功....");
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo-demo-provider.xml"});//根据自己
        Target target = (Target)context.getBean("aspectTargetProxy");
        target.method1();
    }   

执行结果:

 before ...
>>> method1...

下面分析下Spring是怎么实现增强逻辑的,在main方法里,我们看到是通过getBean方法获取的代理类,所以先弄清楚Spring是怎么讲Aop与IOC容器结合在一起的,回头再看下上面的xml配置,org.springframework.aop.framework.ProxyFactoryBean这个类实现了FactoryBean接口,FactoryBean和BeanFactory都是Spring容器的顶级接口,用于管理bean的。主要看下ProxyFactoryBean是怎么实现getObject方法。

public Object getObject() throws BeansException {
        this.initializeAdvisorChain();
        if (this.isSingleton()) {
            return this.getSingletonInstance();
        } else {
            if (this.targetName == null) {
                this.logger.warn("Using non-singleton proxies with singleton targets is often undesirable. Enable prototype proxies by setting the 'targetName' property.");
            }

            return this.newPrototypeInstance();
        }
    }

看下 initializeAdvisorChain方法主要获取配置文件里配置的interceptorNames, 通过beanFactory获取对应的bean后,将配置的advice封装成advisor后加到一个advisor的list里,initializeAdvisorChain() 入口,而advice封装成advisor是在this.addAdvisorOnChainCreation(advice, name);这一行代码里。

private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
        if (!this.advisorChainInitialized) {
        //获取xml文件里配置的interceptorNames,可以回顾下上面的Spring配置里的interceptorNames
            if (!ObjectUtils.isEmpty(this.interceptorNames)) {
                if (this.beanFactory == null) {
                    throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) - cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));
                }

                if (this.interceptorNames[this.interceptorNames.length - 1].endsWith("*") && this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {
                    throw new AopConfigException("Target required after globals");
                }

                String[] var1 = this.interceptorNames;
                int var2 = var1.length;

                for(int var3 = 0; var3 < var2; ++var3) {
                    String name = var1[var3];
                    if (this.logger.isTraceEnabled()) {
                        this.logger.trace("Configuring advisor or advice '" + name + "'");
                    }

                    if (name.endsWith("*")) {
                        if (!(this.beanFactory instanceof ListableBeanFactory)) {
                            throw new AopConfigException("Can only use global advisors or interceptors with a ListableBeanFactory");
                        }

                        this.addGlobalAdvisor((ListableBeanFactory)this.beanFactory, name.substring(0, name.length() - "*".length()));
                    } else {
                        Object advice;
                        if (!this.singleton && !this.beanFactory.isSingleton(name)) {
                            advice = new ProxyFactoryBean.PrototypePlaceholderAdvisor(name);
                        } else {
                            advice = this.beanFactory.getBean(name);
                        }
			 this.addAdvisorOnChainCreation(advice, name);//将advice封装成advisor,并添加到一个advisor队列里
                    }
                }
            }

            this.advisorChainInitialized = true;
        }
    }

初始化advisor后,开始生成代理类,这里会生成两种代理类,一种是基于接口的JDK自带的proxy,一种是基于继承的cglib的代理类,具体生成哪一种代理类,取决于你定义的target有没有实现接口,如果有实现了接口,则使用JDK的proxy,否则使用cglib,这里通过代码来看:

private synchronized Object getSingletonInstance() {
        if (this.singletonInstance == null) {
            this.targetSource = this.freshTargetSource();
            if (this.autodetectInterfaces && this.getProxiedInterfaces().length == 0 && !this.isProxyTargetClass()) {
                Class<?> targetClass = this.getTargetClass();
                if (targetClass == null) {
                    throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
                }

                this.setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
            }

            super.setFrozen(this.freezeProxy);
            this.singletonInstance = this.getProxy(this.createAopProxy());
        }

        return this.singletonInstance;
    }

这里重点看最后一个方法:this.getProxy(copy.createAopProxy());

protected final synchronized AopProxy createAopProxy() {
        if (!this.active) {
            this.activate();
        }

        return this.getAopProxyFactory().createAopProxy(this);
    }

这里仍然看最后一个调用 this.getAopProxyFactory().createAopProxy(this);

protected final synchronized AopProxy createAopProxy() {
       if (!this.active) {
           this.activate();
       }

       return this.getAopProxyFactory().createAopProxy(this);
   }

这里this.getAopProxyFactory().createAopProxy(this); 调用的是DefaultAopProxyFactory类的createAopProxy方法:

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
            return new JdkDynamicAopProxy(config);
        } else {
            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.");
            } else {
                return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));
            }
        }
    }

看到这里,可以看到如果有继承接口就返回JdkDynamicAopProxy,否则返回ObjenesisCglibAopProxy类,这是基于ProxyFactoryBean创建proxy的过程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值