你的位置:首页 > 信息动态 > 新闻中心
信息动态
联系我们

2021SC@SDUSC【软件工程应用与实践】Cocoon代码分析(十五)

2021/12/20 23:36:52

2021SC@SDUSC

这一次的博客是对上一次博客的继续,首先是对spring文件夹里的avalon文件夹的剩余代码进行分析,然后继续分析core文件夹下的其他文件夹的内容。包括spring文件夹下的logger,以及xml文件夹下的avalon,和core文件夹下的一些其他java文件,由于内容很多,我可能会选择重点分析,有一些不太重点的类就一笔带过吧。

文章目录

  • PoolableFactoryBean.java
  • SitemapHelper.java
  • 其他类文件

PoolableFactoryBean.java

这个factory bean向Spring添加了简单的池支持。

一些需要关注的属性:

属性名称属性说明
beanClass
beanFactory相应的bean factory
DEFAULT_MAX_POOL_SIZE池的默认最大大小
interfaces代理的所有接口
name混合组件
semaphore对象,用于同步对get和put方法的访问

构造函数:

重载,创建一个PoolableComponentHandler来管理由指定工厂对象创建的组件池。

public PoolableFactoryBean( String name, String className )
throws Exception {
    this(name, className, DEFAULT_MAX_POOL_SIZE, null);
}

public PoolableFactoryBean( String name, String className, String poolMaxString, Settings settings )
throws Exception {
    String value = poolMaxString;
    if ( settings != null ) {
        value = PropertyHelper.replace(poolMaxString, settings);
    }
    int poolMax = Integer.valueOf(value).intValue();
    this.name = name;
    this.max = ( poolMax <= 0 ? Integer.MAX_VALUE : poolMax );
    this.beanClass = Class.forName(className);
    final HashSet workInterfaces = new HashSet();
    //得到所有接口
    this.guessWorkInterfaces( this.beanClass, workInterfaces );
    //增加 AvalonPoolable
    workInterfaces.add(AvalonPoolable.class);
    this.interfaces = (Class[]) workInterfaces.toArray( new Class[workInterfaces.size()] );
    //创建池列表
    this.ready = new LinkedList();
}

其他重要的方法:

1.dispose():

处理关联的池和工厂。

public void dispose() {
    //准备列表中的任何Poolables都需要处理
    synchronized( this.semaphore ) {
        //移除准备列表中的对象
        for( Iterator iter = this.ready.iterator(); iter.hasNext(); ) {
            Object poolable = iter.next();
            iter.remove();
            this.readySize--;
            this.permanentlyRemovePoolable( poolable );
        }
    }
}

2.enteringPool():

处理特定于服务的方法,将其放入池中

protected void enteringPool( final Object component ) {
    try {
        //处理可回收的对象
        if( component instanceof Recyclable ) {
            ( (Recyclable)component ).recycle();
        }
        if ( this.poolInMethod != null ) {
            this.poolInMethod.invoke(component, null);
        }
    } catch (Exception ignore) {
        //在将组件放回池的过程中,我们忽略异常,因为这不会导致系统崩溃——这是为了与原始Avalon实现兼容
        this.log.error("Exception while putting component '" + component + "' back into the pool.", ignore);
    }
}

3.exitingPool():

处理特定于服务的方法,将其从池中取出

protected void exitingPool( final Object component )
throws Exception {
    if ( this.poolOutMethod != null ) {
        this.poolOutMethod.invoke(component, null);
    }
}

4.getFromPool():

从池中获取一个Poolable。

如果池中有空间,将创建一个新的Poolable。根据构造函数的参数,如果池上的Poolable不可用,该方法可能会阻塞或抛出异常。

public Object getFromPool() throws Exception {
    Object poolable;
    synchronized( this.semaphore ) {
        //在m_ready列表的末尾查找Poolable
        if ( this.readySize > 0 ){
            //poolable已准备好,并在池中等待
            poolable = this.ready.removeLast();
            this.readySize--;
        } else {
            //创建一个新的poolable。如果不能实例化池,可能会抛出异常。
            poolable = this.beanFactory.getBean(this.name);
            this.size++;
            this.highWaterMark = (this.highWaterMark < this.size ? this.size : this.highWaterMark);
        }
    }
    this.exitingPool(poolable);
    return poolable;
}

5.permanentlyRemovePoolable():

永久地从池的活动列表中删除一个池,并销毁它,以便它永远不会被重用

这个方法只被锁定了m_semaphore的线程调用。

protected void permanentlyRemovePoolable( Object poolable ) {
    this.size--;
}

6.putIntoPool():

返回池对象到池

public void putIntoPool( final Object poolable ) {
    this.enteringPool(poolable);
    synchronized( this.semaphore ) {
        if( this.size <= this.max ) {
            this.ready.addLast( poolable );
            this.readySize++;
        } else {
            //创建的Poolables比池中可以容纳的Poolables要多,所以请删除。
            this.permanentlyRemovePoolable( poolable );
        }
    }
}

7.guessWorkInterfaces()以及addInterfaces():

通过扫描一个类实现的所有接口来获取代理的接口列表

private void guessWorkInterfaces( final Class clazz,
                                  final Set workInterfaces ) {
    if ( null != clazz ) {
        this.addInterfaces( clazz.getInterfaces(), workInterfaces );

        this.guessWorkInterfaces( clazz.getSuperclass(), workInterfaces );
    }
}
private void addInterfaces( final Class[] classInterfaces,
                           final Set workInterfaces ) {
    for ( int i = 0; i < classInterfaces.length; i++ ) {
        workInterfaces.add( classInterfaces[i] );
        this.addInterfaces(classInterfaces[i].getInterfaces(), workInterfaces);
    }
}

SitemapHelper.java

有两个比较重要的属性:

  • spring相关的子配置文件的默认位置
    • DEFAULT_CHILD_PROPERTIES_LOCATION
    • DEFAULT_CHILD_SPRING_CONFIGURATION_LOCATION

有一些值得分析的方法:

1.addHeader():

添加xml配置文件的头

protected static void addHeader(StringBuffer buffer) {
    buffer.append("<beans xmlns=\"http://www.springframework.org/schema/beans\"");
    buffer.append(" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
    buffer.append(" xmlns:util=\"http://www.springframework.org/schema/util\"");
    buffer.append(" xmlns:configurator=\"http://cocoon.apache.org/schema/configurator\"");
    buffer.append(" xmlns:avalon=\"http://cocoon.apache.org/schema/avalon\"");
    buffer.append(" xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd");
    buffer.append(" http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd");
    buffer.append(" http://cocoon.apache.org/schema/configurator http://cocoon.apache.org/schema/configurator/cocoon-configurator-1.0.xsd");
    buffer.append(" http://cocoon.apache.org/schema/avalon http://cocoon.apache.org/schema/avalon/cocoon-avalon-1.0.xsd\">\n");
}

2.addFooter():

添加xml配置文件的页脚

protected static void addFooter(StringBuffer buffer) {
    buffer.append("</beans>\n");
}

3.addAttribute():

如果xml流有值,则添加一个属性到它

protected static void addAttribute(StringBuffer buffer, String name, String value) {
    if ( value != null ) {
        buffer.append(' ');
        buffer.append(name);
        buffer.append("=\"");
        buffer.append(value);
        buffer.append("\"");
    }
}

4.isUsingDefaultIncludes():

判断是否默认包括读取此站点地图

protected static boolean isUsingDefaultIncludes(Configuration config) {
    return config.getChild("components").getAttributeAsBoolean("use-default-includes", true);
}

5.getBeanIncludes():

从站点地图获取bean配置的所有包含

protected static List getBeanIncludes(WebApplicationContext webAppContext,
                                      String                contextUrl,
                                      Configuration         sitemap)
throws ConfigurationException {
    final List includes = new ArrayList();
    if ( isUsingDefaultIncludes(sitemap) ) {
        final Resource rsrc = webAppContext.getResource(contextUrl + DEFAULT_CHILD_SPRING_CONFIGURATION_LOCATION);
        if ( rsrc.exists() ) {
            includes.add(DEFAULT_CHILD_SPRING_CONFIGURATION_LOCATION);
        }
    }
    final Configuration[] includeConfigs = sitemap.getChild("components").getChildren("include-beans");
    for(int i = 0 ; i < includeConfigs.length; i++ ) {
        final String dir = includeConfigs[i].getAttribute("dir");
        includes.add(dir);
    }
    return includes;
}

6.getPropertiesIncludes():

从站点地图获取属性的所有包含

protected static List getPropertiesIncludes(WebApplicationContext webAppContext,String contextUrl,Configuration sitemap)
throws ConfigurationException {
    final List includes = new ArrayList();
    if ( isUsingDefaultIncludes(sitemap) ) {
        final Resource rsrc = webAppContext.getResource(contextUrl + DEFAULT_CHILD_PROPERTIES_LOCATION);
        if ( rsrc.exists() ) {
            includes.add(DEFAULT_CHILD_PROPERTIES_LOCATION);
        }
    }
    final Configuration[] includeConfigs = sitemap.getChild("components").getChildren("include-properties");
    for(int i = 0 ; i < includeConfigs.length; i++ ) {
        final String dir = includeConfigs[i].getAttribute("dir");

        includes.add(dir);
    }
    return includes;java
}

7.createContainer():

创建每个站点地图容器

public static WebApplicationContext createContainer(Configuration  config,String sitemapLocation,Monitor fam,ServletContext servletContext)
    throws Exception {
        //先获取父容器
        final WebApplicationContext parentContext = WebAppContextUtils.getCurrentWebApplicationContext();
        final ProcessInfoProvider infoProvider = (ProcessInfoProvider) parentContext.getBean(ProcessInfoProvider.ROLE);
        final Request request = ObjectModelHelper.getRequest(infoProvider.getObjectModel());
        //确定上下文url
        int pos = sitemapLocation.lastIndexOf('/');
        if ( sitemapLocation.lastIndexOf(File.separatorChar) > pos ) {
            pos = sitemapLocation.lastIndexOf(File.separatorChar);
        }
        final String contextUrl = sitemapLocation.substring(0, pos + 1);
        //得到类加载器
        final ClassLoader classloader = Thread.currentThread().getContextClassLoader();        
        //创建根bean定义
        final String definition = createDefinition(request.getSitemapURIPrefix(),sitemapLocation.substring(pos+1),getBeanIncludes(parentContext, contextUrl, config),getPropertiesIncludes(parentContext, contextUrl, config),getGlobalSitemapVariables(config));
        final ChildXmlWebApplicationContext context = new ChildXmlWebApplicationContext(contextUrl,definition);
        context.setServletContext(servletContext);
        context.setParent(parentContext);
        if ( classloader != null ) {
            context.setClassLoader(classloader);
        }
        context.refresh();
        return context;
    }

其他类文件

类的名称类的说明
PoolableProxyHandler所有可合并组件的代理
SettingsContext这是默认上下文实现的扩展。它首先查看settings对象,只有在那里找不到键时,它才委托给父对象。此对象用于设置记录器
ChildLoggerFactoryBeanSpring factory bean来设置一个子公共日志记录器
LoggerFactoryBeanSpring factory bean设置公共日志记录器与指定的类别。如果未设置类别,则使用默认类别“cocoon”
LoggerUtilsCommons日志记录器实用程序
DefaultDOMParser支持Excalibur XML接口的包装器实现
DefaultResolver支持Excalibur XML接口的包装器实现
DefaultSAXParser支持Excalibur XML接口的包装器实现
WiringNotFoundException如果没有找到wiring.xml,则抛出此异常