用PicoContainer和Nanning實現事務管理

PicoContainerNanning實現事務管理

Transaction Manager, with PicoContainer and Nanning

作者:冰雲
Bloghttp://icecloud.51.net
Emailicecloud(AT)sina.com

PicoContainerconstructor injectorIOC容器。Nanningdynamic AOP的一種實現。項目中我用Pico作爲我的微核心,在某些地方需要用到AOP,最典型的是:事務管理(Transaction Manager)。

首先考慮應用的前提,一個DAO需要進行數據庫操作並需要事務。下面是兩個接口聲明:

 

public interface Dao {

    void update();

    Object create();

}

 

public interface TxManager {

    void begin();

    void commit();

    void rollback();

}

 

    如果用OO的實現方法,可能是要讓SampleDao這個實現類同時實現兩個接口等。按照單一職責原則,SampleDao不應該瞭解事務管理,或者,某種情況下,不需要事務處理,這時候應該可以關閉事務。

這裏引入Aspect(方面)來負責事務處理。或者說,事務其實是Service的一個方面。

但是,一個問題是,事務往往和數據庫相關。想要控制事務,必須要能夠啓動事務的Connection,SessionTransaction等等。必須把這些東西同時傳遞給ServiceTxManager

 

public interface ObjectReference{

    Object get();

    void set(Object obj);

}

 

public class DatabaseReference implements ObjectReference{

    private Connection conn ;

   

    public DatabaseReference(){

        // 從某處取得Connection

    }

    Objcet get(){

        return conn;

    }

    void set(Object obj){

        this.conn = (Connection)obj;

    }

}

 

    TxManager的實現類可以擁有一個 DatabaseReference的實例用來獲取和Connection相關的對象。Service的實例也要得到同一個DatabaseReference,這樣TxManager控制同一個Connection的事務纔有效果。

示例如下,系統中我是使用的HibernateSession

 

public class TxManagerImpl implements TxManager {

    private Connection conn;

    public TxManagerImpl(DatabaseReference dref) {

        this.conn = (Connection)dref;

    }

    public void begin() {

        conn.setAutoCommit(false);

    }

    public void commit() {

        conn.commit();

    }

    public void rollback() {

        conn.rollback();

    }

}

 

public class SampleDao implements Dao {

    Connection conn;

    public SampleDao(DatabaseReference dref){

        this.conn = (Connection)dref.get();

    }

    void update() {

        conn.executeQuery("...");

    }

}

 

DaoTxManager之間有了紐帶:DatabaseReference。然而,如果要控制事務,還需要一個控制類,將所有的Dao操作置於事務管理內。

 

 

public class TransactionAspect implements Aspect {

    Pointcut transactionPointcut = P.all();

    TxManager txManager;

 

    public TransactionAspect(TxManager transactionManager) {

        this.txManager = transactionManager;

    }

 

    public void introduce(AspectInstance arg0) {

    }

 

    public void advise(AspectInstance instance) {

        transactionPointcut.advise(instance, new MethodInterceptor() {

            public Object invoke(Invocation invocation) throws Throwable {

                txManager.begin();

                try {

                    Object o = invocation.invokeNext();

                    txManager.commit();

                    return o;

                } catch (Exception e) {

                   txManager.rollback();

                    throw e;

                }

            }

        });

    }

}

 

    這時就可以建立一個調用的實例了,這就需要PicoContainer來負責對象的創建和管理:

 

    MutablePicoContainer pico = new DefaultPicoContainer(

                new CachingComponentAdapterFactory(

                        new NanningComponentAdapterFactory()));

       

        pico.registerComponentImplementation(TxManager.class,

                TxManagerImpl.class);

        pico.registerComponentImplementation(TransactionAspect.class,

                TransactionAspect.class);

        pico.registerComponentImplementation(SampleDao.class);

 

        pico.getComponentInstances();

 

        Dao dao = (Dao) pico.getComponentInstance(SampleDao.class);

        dao.update();

   

上面用到的NanningComponentAdapterFactory,是NanoContainernanning包提供,負責將Nanning實例整合到PicoContainer

log中可

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章