一個簡單的osgi實現框架,可以動態裝載運行,jar包

jopen 9年前發布 | 28K 次閱讀 Java開發 OSGi

hyberbin-osgi

一個簡單的osgi實現框架,可以動態裝載運行,jar包。

運行方式
public static void main(String[] args) throws Exception {
        //模塊名稱
        final String module="comparedb";
        //獲取OSGI容器實例
        final OSGiContainer container = OSGiContainer.getInstance();
        //啟動框架
        container.start();
        //設置模塊安裝成功后的處理
        container.setModuleInstalledHandler(new ModuleInstalledHandler() {
            @Override
            public void moduleInstalled(ModuleLoader loader) {
                //模塊安裝成功后運行該模塊
                Thread.currentThread().setContextClassLoader((ClassLoader)container.getLoader(module));
                container.run(module);
            }
        });
        //創建模塊模型
        ModulesBean modulesBean = new ModulesBean(module, "1.0", new JarFile[]{new JarFile("/codes/myproject/CompareDB/target/CompareDB.jar")},new MainClassRunner("com.hyberbin.main.Main"));
        //從本地maven倉庫中自動解決依賴
        modulesBean.setModuleLoader(new MavenModuleLoaderImpl("/Users/hyberbin/.m2/repository/"));
        //安裝
        container.install(modulesBean);
    }

動態安裝一個SpringMVC模塊

spring-dynamic文件夾下是動態安裝一個SpringMVC模塊的實現

applicationContext-dao.xml配置如下:

 <?xml version="1.0" encoding="UTF-8"?>
 <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
             http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd"
        default-lazy-init="true">

     <bean class="org.springframework.orm.hibernate4.HibernateExceptionTranslator"/>
     <!--<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>-->
     <!--自己實現了一個PersistenceExceptionTranslationPostProcessor,原來的獲取ClassLoader的方式有問題-->
     <bean class="com.XXX.spring.dynamic.aop.UserPersistenceExceptionTranslationPostProcessor"/>
     <!--讓這個sessionFactory來動態路由多個sessionFactory-->
     <bean id="sessionFactory" class="com.XXX.spring.dynamic.factory.DynamicSessionFactory"/>
     <!--這個是將所有的sessionFactory放入Map中-->
     <bean id="sessionFactoryMap" class="java.util.HashMap">
         <constructor-arg>
             <map>
                 <entry key="defaultSessionFactory">
                     <ref bean="defaultSessionFactory"/>
                 </entry>
             </map>
         </constructor-arg>
     </bean>
     <!-- Hibernate SessionFactory -->
     <bean id="defaultSessionFactory" lazy-init="true" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" destroy-method="destroy">
         <property name="dataSource" ref="dataSource"/>
         <property name="configLocation" value="/WEB-INF/hibernate.cfg.xml"/>
         <property name="packagesToScan">
             <list>
                 <value>com.XXX.digitalcampus.**.model</value>
             </list>
         </property>
         <property name="hibernateProperties">
             <props>
                 <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                 <prop key="hibernate.show_sql">false</prop>
                 <prop key="hibernate.format_sql">false</prop>
                 <prop key="hibernate.query.substitutions">true 'Y', false 'N'</prop>
                 <prop key="hibernate.cache.use_second_level_cache">true</prop>
                 <prop key="hibernate.cache.provider_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>
                 <prop key="javax.persistence.validation.mode">none</prop>
                 <!--<prop key="hibernate.current_session_context_class">org.springframework.orm.hibernate4.SpringSessionContext</prop>-->
                 <!--<prop key="hibernate.transaction.auto_close_session">true</prop>-->
                 <!-- Hibernate Search index directory -->
                 <!--<prop key="hibernate.search.default.indexBase">${app.search.index.basedir}</prop>-->
             </props>
             <!-- Turn batching off for better error messages under PostgreSQL -->
             <!-- hibernate.jdbc.batch_size=0 -->
         </property>
     </bean>

     <!-- Transaction manager for a single Hibernate SessionFactory (alternative to JTA) -->
     <!--<bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">-->
         <!--<property name="sessionFactory" ref="sessionFactory"/>-->
     <!--</bean>-->
     <!--動態事務管理器-->
     <bean id="txManager" class="com.XXX.spring.dynamic.factory.DynamicTransactionManager">
         <property name="sessionFactory" ref="sessionFactory"/>
     </bean>
     <!-- Activates scanning of @Repository -->
     <context:component-scan base-package="com.XXX.framework.**.data.hibernate"/>
     <context:component-scan base-package="com.XXX.digitalcampus.**.dao.hibernate"/>

 </beans>

applicationContext-service.xml配置如下:

 <?xml version="1.0" encoding="UTF-8"?>
 <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
             http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
             http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
             http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd"
        default-lazy-init="true">

     <!-- =================================================================== -->
     <!-- AOP: Configuration and Aspects                                      -->
     <!-- =================================================================== -->

     <tx:advice id="txAdvice" transaction-manager="txManager">
         <tx:attributes>
             <tx:method name="save*" rollback-for="com.XXX.framework.core.exception.BusinessException"/>
             <tx:method name="add*" rollback-for="com.XXX.framework.core.exception.BusinessException"/>
             <tx:method name="create*" rollback-for="com.XXX.framework.core.exception.BusinessException"/>
             <tx:method name="insert*" rollback-for="com.XXX.framework.core.exception.BusinessException"/>
             <tx:method name="update*" rollback-for="com.XXX.framework.core.exception.BusinessException"/>
             <tx:method name="merge*" rollback-for="com.XXX.framework.core.exception.BusinessException"/>
             <tx:method name="del*" rollback-for="com.XXX.framework.core.exception.BusinessException"/>
             <tx:method name="remove*" rollback-for="com.XXX.framework.core.exception.BusinessException"/>
             <tx:method name="put*" rollback-for="com.XXX.framework.core.exception.BusinessException"/>
             <tx:method name="execute*" rollback-for="com.XXX.framework.core.exception.BusinessException"
                        no-rollback-for="java.lang.RuntimeException"/>
             <tx:method name="clear*" rollback-for="com.XXX.framework.core.exception.BusinessException"
                        no-rollback-for="java.lang.RuntimeException"/>
             <tx:method name="disable*" rollback-for="com.XXX.framework.core.exception.BusinessException"
                        no-rollback-for="java.lang.RuntimeException"/>
             <tx:method name="use*" rollback-for="com.XXX.framework.core.exception.BusinessException"
                        no-rollback-for="java.lang.RuntimeException"/>

             <!--hibernate4必須配置為開啟事務 否則 getCurrentSession()獲取不到-->
             <tx:method name="get*" read-only="true"/>
             <tx:method name="count*" read-only="true"/>
             <tx:method name="find*" read-only="true"/>
             <tx:method name="list*" read-only="true"/>
             <tx:method name="*" read-only="false"/>
         </tx:attributes>
     </tx:advice>
     <!--這個modulesAdvice主要是為了在ThreadLocal中放入一個模塊名,后面好獲取對應模塊的sessionFactory-->
     <bean id="modulesAdvice" class="com.XXX.spring.dynamic.aop.ServiceMethodBeforeAdvice"/>


     <!--&lt;!&ndash; 配置pointcut,將事務通過aop方式插入到joinpoint &ndash;&gt;-->
     <!--<aop:config>-->
         <!--<aop:pointcut expression="execution(* com.XXX..service.impl.*.*(..))" id="serviceMethod"/>-->
         <!--&lt;!&ndash;這個modulesAdvice主要是為了在ThreadLocal中放入一個模塊名,后面好獲取對應模塊的sessionFactory&ndash;&gt;-->
         <!--<aop:advisor advice-ref="modulesAdvice" pointcut-ref="serviceMethod"/>-->
         <!--<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethod"/>-->
     <!--</aop:config>-->
     <!--<aop:aspectj-autoproxy proxy-target-class="true"/>-->
     <!--這里沒用<aop:>這種高級的配置因為AutoProxyCreator是我自己實現的,之前的AutoProxyCreator不能獲取當前的ClassLoader-->
     <bean id="autoProxyCreator" class="com.XXX.spring.dynamic.aop.AutoProxyCreator"></bean>
     <!--第一個注入modulesAdvice-->
     <bean id="aspectjAspect" class="org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor">
         <property name="advice" ref="modulesAdvice"/>
         <property name="expression" value="execution(* com.XXX..service.impl.*.*(..))"/>
     </bean>
     <!--第二個注入modulesAdvice,注入事務代理,要從第一個切入點中獲取當前模塊的SessionFactory-->
     <bean id="aspectjAspect2" class="org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor">
         <property name="advice" ref="txAdvice"/>
         <property name="expression" value="execution(* com.XXX..service.impl.*.*(..))"/>
     </bean>
     <!--osgi模塊的卸載器-->
     <bean id="moduleUnInstaller" class="com.XXX.spring.dynamic.uninstaller.SpringModuleUninstall"/>
     <!--啟動OSGI容器-->
     <bean id="osgi-container" class="org.jplus.osgi.core.OSGiContainer" factory-method="getInstance" lazy-init="false" init-method="start">
         <property name="moduleUnInstaller" ref="moduleUnInstaller"/>
     </bean>

     <!-- Activates scanning of @Service -->
     <context:component-scan base-package="com.XXX.framework.**.service"/>
     <context:component-scan base-package="com.XXX.digitalcampus.**.service"/>

     <!-- Configure Velocity for sending e-mail -->
     <bean id="velocityEngine" class="org.springframework.ui.velocity.VelocityEngineFactoryBean">
         <property name="velocityProperties">
             <props>
                 <prop key="resource.loader">class</prop>
                 <prop key="class.resource.loader.class">
                     org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
                 </prop>
                 <prop key="velocimacro.library"></prop>
             </props>
         </property>
     </bean>

 </beans>

說明

作者已經實現了用這個框架動態加載自己項目中的模塊.

  • 動態裝載Controller類,并注冊BeanFactory緩存服務.
  • 動態裝載Service類,并注冊Aop服務和BeanFactory緩存服務,開啟Hibernate事務.
  • 動態裝載Hibernate類,并動態生成和加載新的SessionFactory,和BeanFactory緩存服務.
  • 自動將jar包中的jsp文件解壓到web容器下.

問題申明

  • 這種osgi平臺下的模塊中如果有單獨的線程或者不能正常中斷的程序將導致模塊只能加載不能卸載!
  • 程序中不能有System.exit()方法的調用.

項目主頁:http://www.baiduhome.net/lib/view/home/1448203102069

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!