`

扩展 AnnotationSessionFactoryBean 实现domain 对象自动加载

阅读更多
在hibernate和spring集成时,使用annotation方式来替代xml配置方式可以减少项目中配置文件的数量。使项目结构看起来更佳简洁、干净。为此,spring提供了AnnotationSessionFactoryBean 类。但是,在配置的时候,这个类不是很灵活,eg:

Java代码
   <bean id="sessionFactory" class="com.derbysoft.hibernate.core.LocaleAnnotationSessionFactoryBean">     
    <property name="dataSource" ref="dataSource"/>     
    <property name="hibernateProperties">     
        <props>     
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>  
            <prop key="hibernate.show_sql">true</prop>  
        </props>     
    </property>  
   <property name="annotatedClasses">     
        <list>     
            <value>com.example.domain.Role</value>     
            <value>com.example.domain.Permission</value>     
        </list>     
    </property>        
</bean> 

    <bean id="sessionFactory" class="com.derbysoft.hibernate.core.LocaleAnnotationSessionFactoryBean">  
    <property name="dataSource" ref="dataSource"/>  
    <property name="hibernateProperties">  
        <props>  
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
            <prop key="hibernate.show_sql">true</prop>
        </props>  
    </property>
   <property name="annotatedClasses">  
        <list>  
            <value>com.example.domain.Role</value>  
            <value>com.example.domain.Permission</value>  
        </list>  
    </property>     
</bean> 注意到这几行配置代码:

Java代码
<property name="annotatedClasses">     
     <list>     
         <value>com.example.domain.Role</value>     
         <value>com.example.domain.Permission</value>     
     </list>     
</property> 

   <property name="annotatedClasses">  
        <list>  
            <value>com.example.domain.Role</value>  
            <value>com.example.domain.Permission</value>  
        </list>  
   </property> 在你的项目中,你的所有持久化类都需要手动配置到annotatedClasses属性中,很不灵活。所以,为了能过达到更高的灵活性,我们需要自己去扩展AnnotationSessionFactoryBean sessionFacotory工厂类。spring team 也考虑到这一点,为我们提供了预留方法,方便我们实现客户化的功能,eg:

Java代码
/** 
* To be implemented by subclasses that want to to perform custom 
* post-processing of the AnnotationConfiguration object after this 
* FactoryBean performed its default initialization. 
* @param config the current AnnotationConfiguration object 
* @throws HibernateException in case of Hibernate initialization errors 
*/ 
protected void postProcessAnnotationConfiguration(AnnotationConfiguration config)  
        throws HibernateException {  


/**
* To be implemented by subclasses that want to to perform custom
* post-processing of the AnnotationConfiguration object after this
* FactoryBean performed its default initialization.
* @param config the current AnnotationConfiguration object
* @throws HibernateException in case of Hibernate initialization errors
*/
protected void postProcessAnnotationConfiguration(AnnotationConfiguration config)
throws HibernateException {
} 这个方法就是 AnnotationSessionFactoryBean 提供给我们让我们能够实现自己特定功能的方法。因此,我们可以创建一个子类,然后继承AnnotationSessionFactoryBean 实现此方法。

      附件中,是我的详细实代码,需要的可以进行下载。下面,我来详细分析一下我的实现思路,希望大家多多指教。

     大家都知道,在使用spring的时候,spring在加载bean的时候可以按这样一种路径方式来加载,eg:classpath*:com/derbysoft/**/*.class,spring就会加载com.derbysoft包下及其所有子包的class文件,这个叫ant-style模式。在使用struts的时候,我们用annotation注释action的时候。会在web.xml配置这样一段代码:

Java代码
<filter>  
    <filter-name>struts2</filter-name>  
    <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>  
    <init-param>  
        <param-name>actionPackages</param-name>  
        <param-value>com.derbysoft.drental.action</param-value>  
    </init-param>  
</filter> 

<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
<init-param>
    <param-name>actionPackages</param-name>
    <param-value>com.derbysoft.drental.action</param-value>
  </init-param>
</filter> 会指定一个actionPackages属性,然后struts在初始化的时候会认为这个指定的包或子包下,所有的类为action类。(当然在搜索过程中,struts默认会进行过滤,你也可以自己实现过滤条件,eg:没被注解的类不进行加载)

       在我实现的代码中,我参照了这两种模式的实现,底层代码都是依赖spring和struts的核心代码的。

Java代码
/** 
* @see AnnotationSessionFactoryBean#postProcessAnnotationConfiguration(org.hibernate.cfg.AnnotationConfiguration) 
*/ 
@Override 
protected void postProcessAnnotationConfiguration(AnnotationConfiguration config) throws HibernateException {  
    DomainClassLoader[] domainClassLoaders = DomainClassLoaderFactory.buildDomainClassLoader(annotatedClassesLocations);  
    for (DomainClassLoader domainClassLoader : domainClassLoaders) {  
        if (domainClassLoader == null) continue;  
        Set<Class<? extends Class>> annClasses = domainClassLoader.loadAnnotatedClasses();  
          
        for (Class annClass : annClasses) {  
            config.addAnnotatedClass(annClass);  
        }  
    }  


/**
* @see AnnotationSessionFactoryBean#postProcessAnnotationConfiguration(org.hibernate.cfg.AnnotationConfiguration)
*/
@Override
protected void postProcessAnnotationConfiguration(AnnotationConfiguration config) throws HibernateException {
DomainClassLoader[] domainClassLoaders = DomainClassLoaderFactory.buildDomainClassLoader(annotatedClassesLocations);
for (DomainClassLoader domainClassLoader : domainClassLoaders) {
if (domainClassLoader == null) continue;
Set<Class<? extends Class>> annClasses = domainClassLoader.loadAnnotatedClasses();

for (Class annClass : annClasses) {
config.addAnnotatedClass(annClass);
}
}
} 这是整个类的核心代码,我们通过工厂模式来获得不同加载domain方式的实现(spring ant-sttyle模式和struts模式)



Java代码
/** 
* DomainClassLoader 
* @author leo 

*/ 
public static  abstract class DomainClassLoader {  
    protected String[] annotatedClassesLocations;  
      
    public DomainClassLoader(String[] annotatedClassesLocations) {  
        this.annotatedClassesLocations = annotatedClassesLocations;  
    }  
    /** 
     *  
     * @return set collection of of domain class that has annotation 
     */ 
    public abstract Set<Class<? extends Class>> loadAnnotatedClasses();   


/**
* DomainClassLoader
* @author leo
*
*/
public static  abstract class DomainClassLoader {
protected String[] annotatedClassesLocations;

public DomainClassLoader(String[] annotatedClassesLocations) {
this.annotatedClassesLocations = annotatedClassesLocations;
}
/**
*
* @return set collection of of domain class that has annotation
*/
public abstract Set<Class<? extends Class>> loadAnnotatedClasses();
} 这段代码是加载类的抽象,不同的实现都必须去继承它,eg:

Java代码
/** 
*  struts action pattern implements 
* @author leo 
* @see ResolverUtil 
*/ 
public static class PackageDomainClassLoaderProvider extends DomainClassLoader {  
    public PackageDomainClassLoaderProvider(String[] annotatedClassesLocations) {  
        super(annotatedClassesLocations);  
    }  
      
    @Override 
    public Set<Class<? extends Class>> loadAnnotatedClasses() {  
        ResolverUtil<Class> resolver = new ResolverUtil<Class>();  
        resolver.find(new ResolverUtil.AnnotatedWith(Entity.class), annotatedClassesLocations);  
        Set<Class<? extends Class>> actionClasses = resolver.getClasses();  
          
        return actionClasses;  
    }  


/**
*  struts action pattern implements
* @author leo
* @see ResolverUtil
*/
public static class PackageDomainClassLoaderProvider extends DomainClassLoader {
public PackageDomainClassLoaderProvider(String[] annotatedClassesLocations) {
super(annotatedClassesLocations);
}

@Override
public Set<Class<? extends Class>> loadAnnotatedClasses() {
        ResolverUtil<Class> resolver = new ResolverUtil<Class>();
        resolver.find(new ResolverUtil.AnnotatedWith(Entity.class), annotatedClassesLocations);
        Set<Class<? extends Class>> actionClasses = resolver.getClasses();
       
        return actionClasses;
}
}  这个就是struts 包模式的实现,主要的业务是通过ResolverUtil这个struts类来实现的。

  最后通过工厂方法返回一个DomainClassLoader 对象,eg:

Java代码
/** 
* DomainClassLoader Factory 
* @author leo 

*/ 
public static class DomainClassLoaderFactory {  
    /** 
     *  
     * @param includedClass 
     * @param excludedClass 
     * @return array of DomainClassLoader 
     */ 
    public static DomainClassLoader[] buildDomainClassLoader(String[] includedClasses) {  
        List<String> packages = new ArrayList<String>();  
        List<String> regexClasses = new ArrayList<String>();  
        DomainClassLoader[] domainClassLoaders = new DomainClassLoader[2];  
        for (String regexOrpackage : includedClasses) {  
            if (regexOrpackage.contains(ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX)) {  
                regexClasses.add(regexOrpackage);  
            } else {  
                packages.add(regexOrpackage);  
            }  
        }  
        if (packages.size() != 0) {  
            DomainClassLoader domainClassLoader = new PackageDomainClassLoaderProvider(packages.toArray(new String[packages.size()]));  
            domainClassLoaders[0] = domainClassLoader;  
        }  
        if (regexClasses.size() != 0) {  
            DomainClassLoader domainClassLoader = new RegexDomainClassLoaderProvider(regexClasses.toArray(new String[regexClasses.size()]));  
            domainClassLoaders[1] = domainClassLoader;    
        }  
        return domainClassLoaders;  
    }  


/**
* DomainClassLoader Factory
* @author leo
*
*/
public static class DomainClassLoaderFactory {
/**
*
* @param includedClass
* @param excludedClass
* @return array of DomainClassLoader
*/
public static DomainClassLoader[] buildDomainClassLoader(String[] includedClasses) {
List<String> packages = new ArrayList<String>();
List<String> regexClasses = new ArrayList<String>();
DomainClassLoader[] domainClassLoaders = new DomainClassLoader[2];
for (String regexOrpackage : includedClasses) {
if (regexOrpackage.contains(ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX)) {
regexClasses.add(regexOrpackage);
} else {
packages.add(regexOrpackage);
}
}
if (packages.size() != 0) {
DomainClassLoader domainClassLoader = new PackageDomainClassLoaderProvider(packages.toArray(new String[packages.size()]));
domainClassLoaders[0] = domainClassLoader;
}
if (regexClasses.size() != 0) {
DomainClassLoader domainClassLoader = new RegexDomainClassLoaderProvider(regexClasses.toArray(new String[regexClasses.size()]));
domainClassLoaders[1] = domainClassLoader;
}
return domainClassLoaders;
}
} 最后,我配置的时候只需这样:

Java代码
<property name="annotatedClassesLocations">     
     <list>     
         <value>classpath*:com/example/**/domain/*.class</value>   
         <value>com.example.domain</value>     
     </list>     
</property>  

   <property name="annotatedClassesLocations">  
        <list>  
            <value>classpath*:com/example/**/domain/*.class</value>
            <value>com.example.domain</value>  
        </list>  
    </property>  spring在加载的时候,会去匹配类路径下com.example.xxx.domain.xxx.class 类和com.example.domain包及其子包下所有的类。至于具体的实现细节请下载附件

分享到:
评论
1 楼 capturefuture 2011-09-28  
AnnotationSessionFacotoryBean中有一个属性叫,annotatedPackages可以直接填包的名字啊,不用自己扩展吧

相关推荐

    维生药业小项目 SSH简单学习项目

    class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"&gt; &lt;ref bean="dataSource"&gt;&lt;/ref&gt; &lt;prop key="hibernate.dialect"&gt;org.hibernate.dialect....

    SpringMVC+Hibernate全注解整合

    对web包中的所有类进行扫描,以完成Bean创建和自动依赖注入的功能 mvc:annotation-driven --&gt; &lt;!-- 扫描包 --&gt; &lt;context:annotation-config/&gt; *" /&gt; ...

    spring_MVC源码

    18. class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"&gt; 19. &lt;property name="dataSource" ref="dataSource" /&gt; 20. &lt;property name="hibernateProperties"&gt; 21. &lt;props&gt; 22...

    SpringMVC-SSH全注解

    &lt;bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"&gt; &lt;value&gt;com.org.core.entity&lt;/value&gt; ${hibernate....

    struts2.3+hibernate3.6+spring3.1整合的纯xml配置的小项目

    class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"&gt; &lt;property name="dataSource" ref="dataSource"&gt;&lt;/property&gt; org.whvcse.model.Userinfo ...

    SPRING API 2.0.CHM

    AnnotationSessionFactoryBean AnnotationTransactionAttributeSource AnnotationUtils AntPathMatcher AopConfigException AopContext AopInvocationException AopNamespaceHandler AopNamespaceUtils ...

Global site tag (gtag.js) - Google Analytics