在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包及其子包下所有的类。至于具体的实现细节请下载附件
分享到:
相关推荐
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <ref bean="dataSource"></ref> <prop key="hibernate.dialect">org.hibernate.dialect....
对web包中的所有类进行扫描,以完成Bean创建和自动依赖注入的功能 mvc:annotation-driven --> <!-- 扫描包 --> <context:annotation-config/> *" /> ...
18. class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> 19. <property name="dataSource" ref="dataSource" /> 20. <property name="hibernateProperties"> 21. <props> 22...
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <value>com.org.core.entity</value> ${hibernate....
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property> org.whvcse.model.Userinfo ...
AnnotationSessionFactoryBean AnnotationTransactionAttributeSource AnnotationUtils AntPathMatcher AopConfigException AopContext AopInvocationException AopNamespaceHandler AopNamespaceUtils ...