zoukankan      html  css  js  c++  java
  • AOP动态代理解析4-代理的创建

    做完了增强器的获取后就可以进行代理的创建了

    AnnotationAwareAspectJAutoProxyCreator->postProcessAfterInitialization->wrapIfNecessary
    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        .....................
        // Create proxy if we have advice.
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
        if (specificInterceptors != DO_NOT_PROXY) {
            this.advisedBeans.put(cacheKey, Boolean.TRUE);
            Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
            this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        }
        ......................
    }

    代理获取分两个步骤:

    1. 增强器的封装
    2. 代理生成 
    protected Object createProxy(
            Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
    
        ProxyFactory proxyFactory = new ProxyFactory();
        //获取当前类中相关属性
        proxyFactory.copyFrom(this);
        //检查proxyTargeClass设置以及preserveTargetClass属性  
        //决定对于给定的bean是否应该使用targetClass而不是他的接口代理 
        if (!shouldProxyTargetClass(beanClass, beanName)) {
            // Must allow for introductions; can't just set interfaces to
            // the target's interfaces only.
            Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, this.proxyClassLoader);
            for (Class<?> targetInterface : targetInterfaces) {
                //添加代理接口
                proxyFactory.addInterface(targetInterface);
            }
        }
        //增强器的封装
       Advisor[] advisors
    = buildAdvisors(beanName, specificInterceptors); for (Advisor advisor : advisors) { //加入增强器 proxyFactory.addAdvisor(advisor); } //设置要代理的类 proxyFactory.setTargetSource(targetSource); //为子类提供了定制的函数customizeProxyFactory,子类可以在此函数中进行对ProxyFactory的进一步封装。 customizeProxyFactory(proxyFactory); //缺省值为false即在代理被配置之后,不允许修改代理的配置。 proxyFactory.setFrozen(this.freezeProxy); if (advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } return proxyFactory.getProxy(this.proxyClassLoader); }

    其中,封装Advisor并加入到ProxyFactory中以及创建代理是两个相对繁琐的过程,可以通过ProxyFactory提供的addAdvisor方法直接将增强器置入代理创建工厂中,但是将拦截器封装为增强器还是需要一定的逻辑的。

    增强器的封装

    protected Advisor[] buildAdvisors(String beanName, Object specificInterceptors[])  {  
        //解析注册的所有interceptorName  
        Advisor commonInterceptors[] = resolveInterceptorNames();  
        List allInterceptors = new ArrayList();  
        if(specificInterceptors != null)  
        {  
            //加入拦截器  
            allInterceptors.addAll(Arrays.asList(specificInterceptors));  
            if(commonInterceptors != null)  
                if(applyCommonInterceptorsFirst)  
                    allInterceptors.addAll(0, Arrays.asList(commonInterceptors));  
                else  
                    allInterceptors.addAll(Arrays.asList(commonInterceptors));  
        }  
        if(logger.isDebugEnabled())  
        {  
            int nrOfCommonInterceptors = commonInterceptors == null ? 0 : commonInterceptors.length;  
            int nrOfSpecificInterceptors = specificInterceptors == null ? 0 : specificInterceptors.length;  
            logger.debug((new StringBuilder())
              .append("Creating implicit proxy for bean '")
              .append(beanName).append("' with ").append(nrOfCommonInterceptors)
              .append(" common interceptors and ").append(nrOfSpecificInterceptors)
              .append(" specific interceptors").toString()); } Advisor advisors[] = new Advisor[allInterceptors.size()]; for(int i = 0; i < allInterceptors.size(); i++) //拦截器进行封装转化为Advisor advisors[i] = advisorAdapterRegistry.wrap(allInterceptors.get(i)); return advisors; } public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException { //如果要封装的对象本身就是Advisor类型的那么无需做过多处理 if(adviceObject instanceof Advisor) return (Advisor)adviceObject; //因为此封装只对Advisor和Advice两种类型的数据有效,如果不是将不能封装 if(!(adviceObject instanceof Advice)) throw new UnknownAdviceTypeException(adviceObject); Advice advice = (Advice)adviceObject; if(advice instanceof MethodInterceptor) //如果是MethodInterceptor类型则使用DefaultPointcutrAdvisor封装 return new DefaultPointcutAdvisor(advice); //如果存在Advisor类型的适配器那么也同样需要进行封装 for(Iterator i$ = adapters.iterator(); i$.hasNext();) { AdvisorAdapter adapter = (AdvisorAdapter)i$.next(); if(adapter.supportsAdvice(advice)) return new DefaultPointcutAdvisor(advice); } throw new UnknownAdviceTypeException(advice); }

    由于Spring中涉及过多的拦截器,增强器,增强方法等方式来对逻辑进行增强,所以非常有必要统一封装成Advisor来进行代理的创建,完成了增强的封装过程,那么解析最终的一步就是代理的创建获取了。

    代理生成

    public Object getProxy(ClassLoader classLoader)  {  
        return createAopProxy().getProxy(classLoader);  //JdkDynamicAopProxy.getProxy()
    } protected final synchronized AopProxy createAopProxy(){ if(!active) activate(); //创建代理  return getAopProxyFactory().createAopProxy(this); } 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()) return new JdkDynamicAopProxy(config); else return CglibProxyFactory.createCglibProxy(config); } else { return new JdkDynamicAopProxy(config); } }

    到此已经完成了代理的创建,现在从源代码的角度分析,看看到底Spring是如何选择代理方式的。
    从if中的判断条件可以看到3个方面影响着spring的判断

    1. optimize:用来控制通过CGLIB创建的代理是否使用激进的优化策略。除非完全了解AOP代理是如何优化,否则不推荐用户使用这个设置,目前这个属性仅用于CGLIB代理,对于JDK动态代理(缺省代理)无效。
    2. proxyTargetClass:这个属性为true时,目标类本身被代理而不是目标类的接口。如果这个属性值被设为true,CGLIB代理将被创建。
    3. hasNOUser Supplied Proxy Interfaces:是否存在代理接口。

    至此就是创建代理的过程,后面就是两种动态代理的生成proxy的方式和底层的实现。见Spring AOP 详解的jdk源码分析和cglib分析

    下面是对JDK与Cglib方式的总结:

    1. 如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP。
    2. 如果目标对象实现了接口,可以强制使用CGLIB实现AOP。
    3. 如果目标对象没有实现了接口,必须采用CGLIB库。

    Spring会自动在JDK动态代理和CGLIB之间转换。

    如何强制使用CGLIB实现AOP?

    1. 添加CGLIB库,spring_home/cglib/*.jar。
    2. 在Spring配置文件中加入。

    JDK动态代理和CGLIB字节码生成的区别?

    1. JDK动态代理只能对实现了接口的类生成代理,而不能针对类。
    2. CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,因为是继承,所以该类或方法最好不要声明成final。
  • 相关阅读:
    word设置的密码忘了怎么办?
    Navicat Report Viewer 设置 HTTP 的方法
    如何处理Navicat Report Viewer 报表
    excel密码忘记了怎么办
    Beyond Compare文本比较搜索功能详解
    Popular Cows POJ
    Problem B. Harvest of Apples HDU
    网络流模型整理
    The Shortest Statement CodeForces
    Vasya and Multisets CodeForces
  • 原文地址:https://www.cnblogs.com/wade-luffy/p/6077277.html
Copyright © 2011-2022 走看看