當(dāng)柳上原的風(fēng)吹向天際的時候...

          真正的快樂來源于創(chuàng)造

            BlogJava :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
            368 Posts :: 1 Stories :: 201 Comments :: 0 Trackbacks

          權(quán)限子系統(tǒng)與文檔處理子系統(tǒng)交織的弊病

          如同一個成規(guī)模的公司一樣,對于一個成規(guī)模的應(yīng)用來說,內(nèi)中會存在著各種子系統(tǒng)以執(zhí)行不同的功能,而且為了協(xié)調(diào)工作,它們往往是交織在一起,就像上一個版本中權(quán)限子系統(tǒng)與文檔處理子系統(tǒng)交織一樣。

          子系統(tǒng)交織是必要的,但子系統(tǒng)間過多過緊密的耦合并不合理。因?yàn)榻豢棔黾榆浖到y(tǒng)的熵值,使得系統(tǒng)隨著功能的增加和細(xì)化變得越來越復(fù)雜而難于控制,最后不得不推倒重來,給個人和公司帶來巨大的損失。這是軟件業(yè)普遍的問題,在國內(nèi)公司和外包公司都不罕見。

          因此,在程序的編寫過程中,程序員必須有意識的減少子系統(tǒng)之間的交織,使它們離散化,利用Spring的AOP可以有效幫助我們做到這一點(diǎn)。對于簡單值權(quán)限系統(tǒng),使用AOP進(jìn)行子系統(tǒng)離散化的具體思路如下:

          1.將DocService中負(fù)責(zé)權(quán)限的代碼(屬性和函數(shù))都分離,放置到一個專門的權(quán)限處理類PrivilegeService中。
          2.使用Spring的ProxyFactoryBean,做成DocService的代理,讓PrivilegeService作為它的前置處理器。
          3.在PrivilegeService的before方法中,執(zhí)行權(quán)限檢查,如果權(quán)限值不夠則拋出異常。

          分離后DocService簡潔的代碼
          package com.heyang.aopstyle.service;

          import com.heyang.traditonal.domain.Doc;
          import com.heyang.traditonal.domain.User;
          import com.heyang.traditonal.service.IDocService;

          /**
           * 為領(lǐng)域?qū)ο驞oc提供服務(wù)
           * 
           * 
          @author 何楊(heyang78@gmail.com)
           * 
           * 
          @since 2008-12-30 下午05:13:29
           * 
          @version 1.00
           
          */

          public class DocService implements IDocService {
              
          public void add(Doc doc, User user) {
                  System.out.println(
          "" + doc + "交由dao處理(存入數(shù)據(jù)庫)");
              }


              
          public void delete(Doc doc, User user) {
                  System.out.println(
          "" + doc + "交由dao處理(從數(shù)據(jù)庫刪除)");
              }


              
          public void update(Doc doc, User user) {
                  System.out.println(
          "" + doc + "交由dao處理(更新數(shù)據(jù)庫中對應(yīng)的記錄)");
              }

          }

          新組建的PrivilegeService類
          package com.heyang.aopstyle.service;

          import java.lang.reflect.Method;

          import org.springframework.aop.MethodBeforeAdvice;

          import com.heyang.aopstyle.exception.PrivilegeNotEnoughException;
          import com.heyang.traditional2.dao.PrivilegeDao;
          import com.heyang.traditonal.domain.User;

          /**
           * 實(shí)現(xiàn)權(quán)限子系統(tǒng)
           * 
          @author: 何楊(heyang78@gmail.com)
           * @date: 2009-1-2-下午04:19:13
           
          */

          public class PrivilegeService implements MethodBeforeAdvice{
              
          private PrivilegeDao privilegeDao;
              
              
          // 添加doc需要的權(quán)限名
              private String addDocPrivilegeName;
              
              
          // 刪除doc需要的權(quán)限名
              private String deleteDocPrivilegeName;
              
              
          // 更新doc需要的權(quán)限名
              private String updateDocPrivilegeName;
              
              
          /**
               * 在IDocService的實(shí)際方法開始前進(jìn)行前置處理--權(quán)限檢查
               
          */

              
          public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
                  
          // 取得方法名
                  String mothodName=arg0.getName();
                  
                  
          // 取得用戶權(quán)限
                  User user=(User)arg1[1];
                  
          int userPrivilegeValue=user.getPrivilegePoint();
                  
                  
          // 根據(jù)方法名判斷用戶是否達(dá)到了需要的權(quán)限,否則拋出異常
                  if("add".equals(mothodName)){
                      
          if(userPrivilegeValue<=getPrivilegeValueBy(addDocPrivilegeName)){
                          
          throw new PrivilegeNotEnoughException("用戶權(quán)限必須達(dá)到"+getPrivilegeValueBy(addDocPrivilegeName)+"才能執(zhí)行添加操作");
                      }

                  }

                  
          else if("delete".equals(mothodName)){
                      
          if(userPrivilegeValue<=getPrivilegeValueBy(deleteDocPrivilegeName)){
                          
          throw new PrivilegeNotEnoughException("用戶權(quán)限必須達(dá)到"+getPrivilegeValueBy(deleteDocPrivilegeName)+"才能執(zhí)行刪除操作");
                      }

                  }

                  
          else if("update".equals(mothodName)){
                      
          if(userPrivilegeValue<=getPrivilegeValueBy(updateDocPrivilegeName)){
                          
          throw new PrivilegeNotEnoughException("用戶權(quán)限必須達(dá)到"+getPrivilegeValueBy(updateDocPrivilegeName)+"才能執(zhí)行更新操作");
                      }

                  }

              }

              
              
              
          private int getPrivilegeValueBy(String name){
                  
          return privilegeDao.getValueBy(name);
              }


              
          public PrivilegeDao getPrivilegeDao() {
                  
          return privilegeDao;
              }


              
          public void setPrivilegeDao(PrivilegeDao privilegeDao) {
                  
          this.privilegeDao = privilegeDao;
              }


              
          public String getAddDocPrivilegeName() {
                  
          return addDocPrivilegeName;
              }


              
          public void setAddDocPrivilegeName(String addDocPrivilegeName) {
                  
          this.addDocPrivilegeName = addDocPrivilegeName;
              }


              
          public String getDeleteDocPrivilegeName() {
                  
          return deleteDocPrivilegeName;
              }


              
          public void setDeleteDocPrivilegeName(String deleteDocPrivilegeName) {
                  
          this.deleteDocPrivilegeName = deleteDocPrivilegeName;
              }


              
          public String getUpdateDocPrivilegeName() {
                  
          return updateDocPrivilegeName;
              }


              
          public void setUpdateDocPrivilegeName(String updateDocPrivilegeName) {
                  
          this.updateDocPrivilegeName = updateDocPrivilegeName;
              }

          }

          起輔助作用的PrivilegeNotEnoughException類,因?yàn)椴幌敫淖兘涌冢ɑ虿荒芨淖兘涌冢┕拾旬惓n愋投ㄎ贿\(yùn)行期異常:
          package com.heyang.aopstyle.exception;

          /**
           * 權(quán)限不足異常
           * 
          @author: 何楊(heyang78@gmail.com)
           * @date: 2009-1-2-下午04:02:50
           
          */

          public class PrivilegeNotEnoughException extends RuntimeException{
              
          private static final long serialVersionUID = -6594794529337011115L;

              
          public PrivilegeNotEnoughException(String msg){
                  
          super(msg);
              }

          }

          最終配置文件
          <?xml version="1.0" encoding="UTF-8"?>
          <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
          <beans>
            
          <!-- 數(shù)據(jù)源 -->
            
          <bean id="dataSource"
              class
          ="org.springframework.jdbc.datasource.DriverManagerDataSource">
              
          <property name="driverClassName"
                value
          ="org.gjt.mm.mysql.Driver">
              
          </property>
              
          <property name="url" value="jdbc:mysql://127.0.0.1/test">
              
          </property>
              
          <property name="username" value="root"></property>
              
          <property name="password" value="hy"></property>
            
          </bean>

            
          <!-- 用于訪問數(shù)據(jù)庫的jdbcTemplate -->
            
          <bean id="jdbcTemplate"
              class
          ="org.springframework.jdbc.core.JdbcTemplate">
              
          <property name="dataSource">
                
          <ref bean="dataSource" />
              
          </property>
            
          </bean>
            
            
          <!-- 用于訪問數(shù)據(jù)庫的PrivilegeTB表,按權(quán)限名取出權(quán)限值的數(shù)據(jù)庫訪問類 -->
            
          <bean id="privilegeDao"
              class
          ="com.heyang.traditional2.dao.PrivilegeDao">
              
          <property name="jdbcTemplate">
                
          <ref bean="jdbcTemplate" />
              
          </property>
            
          </bean>

            
          <!-- 用于文件處理的IDocService實(shí)現(xiàn)類DocService -->
            
          <bean id="docService" class="com.heyang.aopstyle.service.DocService"/>
            
            
          <!-- 在執(zhí)行docService的實(shí)際方法前進(jìn)行權(quán)限檢查 -->
            
          <bean id="privilegeService" class="com.heyang.aopstyle.service.PrivilegeService">
              
          <property name="privilegeDao">
                
          <ref bean="privilegeDao" />
              
          </property>
              
          <property name="addDocPrivilegeName" value="addDocPrivilege" />
              
          <property name="deleteDocPrivilegeName" value="deleteDocPrivilege" />
              
          <property name="updateDocPrivilegeName" value="updateDocPrivilege" />   
            
          </bean>
            
            
          <!-- docService的代理對象 -->
            
          <bean id="docServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
              
          <property name="proxyInterfaces">
                
          <value>com.heyang.traditonal.service.IDocService</value>
              
          </property>
              
          <property name="interceptorNames">
                
          <list>
                  
          <value>privilegeService</value>
                
          </list>
              
          </property>
              
          <property name="target">
                
          <ref bean="docService"/>
              
          </property>
            
          </bean>
          </beans>

          業(yè)務(wù)處理模擬過程
          package com.heyang.aopstyle;

          import org.springframework.context.ApplicationContext;
          import org.springframework.context.support.ClassPathXmlApplicationContext;

          import com.heyang.aopstyle.exception.PrivilegeNotEnoughException;
          import com.heyang.traditonal.domain.Doc;
          import com.heyang.traditonal.domain.User;
          import com.heyang.traditonal.service.IDocService;


          public class Main{
              
          public static void main(String[] args){
                  ApplicationContext ctx 
          = new ClassPathXmlApplicationContext("aopCtx.xml");
                  
                  IDocService docService
          =(IDocService)ctx.getBean("docServiceProxy");
                  
                  Doc doc
          =new Doc("論美國次貸危機(jī)的產(chǎn)生及影響");
                  User user
          =new User("中科院經(jīng)濟(jì)所研究員",50);
                  
                  
          // 用戶向系統(tǒng)添加文章
                  try{
                      docService.add(doc, user);
                  }

                  
          catch(PrivilegeNotEnoughException ex){
                      System.out.println(ex.getMessage());
                  }

                  
                  
          // 用戶向系統(tǒng)更新文章
                  try{
                      doc.setName(
          "論美國次貸危機(jī)的產(chǎn)生及影響和我國應(yīng)該采取的應(yīng)對措施");
                      docService.update(doc, user);
                  }

                  
          catch(PrivilegeNotEnoughException ex){
                      System.out.println(ex.getMessage());
                  }

                  
                  
          // 用戶從系統(tǒng)撒刪除文章
                  try{
                      docService.delete(doc, user);
                  }

                  
          catch(PrivilegeNotEnoughException ex){
                      System.out.println(ex.getMessage());
                  }

              }

          }


          輸出
          2009-01-02 16:26:53,406 DEBUG [main] (DriverManagerDataSource.java:289- Creating new JDBC Connection to [jdbc:mysql://127.0.0.1/test]
          2009-01-02 16:26:56,578 DEBUG [main] (DataSourceUtils.java:312- Returning JDBC Connection to DataSource
          將文件 名
          =論美國次貸危機(jī)的產(chǎn)生及影響交由dao處理(存入數(shù)據(jù)庫)
          2009-01-02 16:26:56,593 DEBUG [main] (JdbcTemplate.java:382- Executing SQL query [select value from PrivilegeTB where name='updateDocPrivilege' ]
          2009-01-02 16:26:56,593 DEBUG [main] (DataSourceUtils.java:112- Fetching JDBC Connection from DataSource
          2009-01-02 16:26:56,593 DEBUG [main] (DriverManagerDataSource.java:289- Creating new JDBC Connection to [jdbc:mysql://127.0.0.1/test]
          2009-01-02 16:26:56,640 DEBUG [main] (DataSourceUtils.java:312- Returning JDBC Connection to DataSource
          將文件 名
          =論美國次貸危機(jī)的產(chǎn)生及影響和我國應(yīng)該采取的應(yīng)對措施交由dao處理(更新數(shù)據(jù)庫中對應(yīng)的記錄)
          2009-01-02 16:26:56,640 DEBUG [main] (JdbcTemplate.java:382- Executing SQL query [select value from PrivilegeTB where name='deleteDocPrivilege' ]
          2009-01-02 16:26:56,640 DEBUG [main] (DataSourceUtils.java:112- Fetching JDBC Connection from DataSource
          2009-01-02 16:26:56,640 DEBUG [main] (DriverManagerDataSource.java:289- Creating new JDBC Connection to [jdbc:mysql://127.0.0.1/test]
          2009-01-02 16:26:56,703 DEBUG [main] (DataSourceUtils.java:312- Returning JDBC Connection to DataSource
          2009-01-02 16:26:56,859 DEBUG [main] (JdbcTemplate.java:382- Executing SQL query [select value from PrivilegeTB where name='deleteDocPrivilege' ]
          2009-01-02 16:26:56,859 DEBUG [main] (DataSourceUtils.java:112- Fetching JDBC Connection from DataSource
          2009-01-02 16:26:56,859 DEBUG [main] (DriverManagerDataSource.java:289- Creating new JDBC Connection to [jdbc:mysql://127.0.0.1/test]
          2009-01-02 16:26:56,953 DEBUG [main] (DataSourceUtils.java:312- Returning JDBC Connection to DataSource
          用戶權(quán)限必須達(dá)到60才能執(zhí)行刪除操作


          例程下載
          http://www.aygfsteel.com/Files/heyang/AOPPrivilegeSample20090102170039.rar

          需要自行載入的包為:
          commons-logging-1.0.4.jar,log4j-1.2.14.jar,spring.jar,mysql-connector-java-5.0.6-bin.jar
          posted on 2009-01-02 16:54 何楊 閱讀(779) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 栖霞市| 尉犁县| 云霄县| 富川| 比如县| 南昌市| 民丰县| 德兴市| 曲靖市| 辽阳市| 南昌县| 石狮市| 广元市| 千阳县| 中阳县| 房山区| 金华市| 望江县| 尚志市| 平邑县| 鄂伦春自治旗| 安泽县| 海林市| 崇信县| 晴隆县| 华阴市| 沾化县| 凤翔县| 庆安县| 大埔县| 宁晋县| 天柱县| 兴和县| 靖西县| 元氏县| 腾冲县| 镇原县| 寻甸| 尤溪县| 上蔡县| 洛南县|