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对象,只有在那里找不到键时,它才委托给父对象。此对象用于设置记录器 |
ChildLoggerFactoryBean | Spring factory bean来设置一个子公共日志记录器 |
LoggerFactoryBean | Spring factory bean设置公共日志记录器与指定的类别。如果未设置类别,则使用默认类别“cocoon” |
LoggerUtils | Commons日志记录器实用程序 |
DefaultDOMParser | 支持Excalibur XML接口的包装器实现 |
DefaultResolver | 支持Excalibur XML接口的包装器实现 |
DefaultSAXParser | 支持Excalibur XML接口的包装器实现 |
WiringNotFoundException | 如果没有找到wiring.xml,则抛出此异常 |