Spring Aop之我见

                                深入理解AOP (SpringGuide随笔)<o:p></o:p>

前言:最近2年一阵春(Spring)风吹变了世界各地,当然也把俺吹的昏头转向(差点没吹趴下,这那里是春风啊,简直就是头骨的阴风,: ),故写一篇小文来迎接一哈这阵阵春风,希望对学习Spring的人,有一些帮助。好那,不说废话那,进入正题。

<o:p> </o:p>

Spring 中提供的AOP支持,是基于动态的AOP机制实现的。

这里什么是动态的的AOP呢?

即通过动态的Proxy模式,在目标对象的方法调用的前后插入相应的处理代码。

那么是么是动态的Proxy模式呢?

Spring中的动态Proxy模式,是基于Java Dynamic Proxy(面向Interface)和CGLIB(面向Class)的实现。

那什么是Dynamic ProxyJDK1.3版本中引入的一种动态代理机制。它是Proxy模式的一种动态实现版本。

             

Proxy模式又分为两种

A:静态Proxy模式

B:动态Proxy模式

首先我们来看看什么是静态Proxy模式

假设我们有一个UserDAO接口以及一个实现类UserDAOImp

UserDAO.Java

Public interface UserDAO{

   Public void saveUser(User user);

}

UserDAOImp.java

Public class UserDAOImp implents UserDAO{

   Public void saveUser(User user){

   ………………………

}

}

<o:p> </o:p>

UserDAOProxy.java

Public class UserDAOProxy implments UserDAO{

//可以看到代理UserDAOProxy也是实现那UserDAO

·                // UserDAOProxy instanceof UserDAO 将返回TRUE

<o:p> </o:p>

     Private UserDAO   userDAO;

     Public UserDAOProxy(UserDAO   userDAO){

        This.userDAO= userDAO;

}

 Public void saveUser(User user){

     Transaction tx =null;<o:p></o:p>

Try{<o:p></o:p>

Tx=new Transaction();<o:p></o:p>

UserDAO.saveUser(user);

}catch(Excption e){<o:p></o:p>

     Tx.rollBack();<o:p></o:p>

}<o:p></o:p>

}

}

当外部调用UserDAOUserDAOImpsaveUser方法的时候,实际上是调用了UserDAOProxysaveUser方法

注意UserDAOProxy同样也实现了UserDAO接口,对于调用者来说,saveuser方法的使用完全相同,不同的是内部的实现机制发生了一些改变,UserDAOProxy中为UserDAO.saveUser方法加了一层JTA事务管理的外壳。

好那,现在我们看看如何创建一个动态代理类的实例<o:p></o:p>

java.lang.reflect.Proxy用于Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。<o:p></o:p>

创建某一接口 Foo 的代理:

       Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
                                          new Class[] { Foo.class },
                                          handler);
<o:p> </o:p>

public static Object newProxyInstance(ClassLoader loader,<o:p></o:p>

                                      Class[] interfaces,<o:p></o:p>

                                      InvocationHandler h)<o:p></o:p>

                               throws IllegalArgumentException<o:p></o:p>

返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。此方法相当于: <o:p></o:p>

参数: <o:p></o:p>

loader - 定义代理类的类加载器 <o:p></o:p>

interfaces - 代理类要实现的接口列表 <o:p></o:p>

h - 指派方法调用的调用处理程序 <o:p></o:p>

返回: <o:p></o:p>

一个带有代理类的指定调用处理程序的代理实例,它由指定的类加载器定义,并实现指定的接口 <o:p></o:p>

动态代理类(以下简称为代理类)是一个实现在创建类时在运行时指定的接口列表的类。
 代理接口 是代理类实现的一个接口。 
代理实例 是代理类的一个实例。 每个代理实例都有一个关联的调用处理程序 对象
  • 由于代理类将实现所有在其创建时指定的接口,所以对其 Class 对象调用 getInterfaces 将返回一个包含相同接口列表的数组(按其创建时指定的顺序),对其 Class 对象调用 getMethods 将返回一个包括这些接口中所有方法的 Method 对象的数组,并且调用 getMethod 将会在代理接口中找到期望的一些方法。 <o:p></o:p>
每个代理实例都有一个关联的调用处理程序,它会被传递到其构造方法中。静态 Proxy.getInvocationHandler 方法将返回与作为其参数传递的代理实例相关的调用处理程序。
public interface InvocationHandler{
Object invoke(Object proxy,
                  Method method,
                  Object[] args)
                  throws Throwable}

参数: <o:p></o:p>

proxy - 在其上调用方法的代理实例 <o:p></o:p>

method - 对应于在代理实例上调用的接口方法 Method 实例。Method 对象的声明类将是在其中声明方法的接口,该接口可以是代理类赖以继承方法的代理接口的超接口。 <o:p></o:p>

args - 包含传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,则为 null。基本类型的参数被包装在适当基本包装器类(如 java.lang.Integer java.lang.Boolean)的实例中。<o:p></o:p>

<o:p> </o:p>

<o:p> </o:p>

Spring HibernateDaoSupport 基类提供了访问与当前事务绑定的 Session 对象的函数,因而能保证在这种情况下异常的正确转化。类似的函数同样可以在 SessionFactoryUtils 类中找到,但他们以静态方法的形式出现。 值得注意的是,通常将一个false作为参数(表示是否允许创建)传递到 getSession(..) 法中进行调用。 此时,整个调用将在同一个事务内完成(它的整个生命周期由事务控制,避免了关闭返回的 Session 的需要)。 <o:p></o:p>

public class ProductDaoImpl extends HibernateDaoSupport implements ProductDao {<o:p></o:p>

<o:p> </o:p>

    public Collection loadProductsByCategory(String category)<o:p></o:p>

            throws DataAccessException, MyException {<o:p></o:p>

<o:p> </o:p>

        Session session = getSession(getSessionFactory(), false);<o:p></o:p>

        try {<o:p></o:p>

            List result = session.find(<o:p></o:p>

                "from test.Product product where product.category=?",<o:p></o:p>

                category, Hibernate.STRING);<o:p></o:p>

            if (result == null) {<o:p></o:p>

                throw new MyException("invalid search result");<o:p></o:p>

            }<o:p></o:p>

            return result;<o:p></o:p>

        }<o:p></o:p>

        catch (HibernateException ex) {<o:p></o:p>

            throw convertHibernateAccessException(ex);<o:p></o:p>

        }<o:p></o:p>

    }<o:p></o:p>

}<o:p></o:p>

这种直接使用Hibernate访问代码的主要好处在于它允许你在数据访问代码中抛出checked exception,而 HibernateTemplate 却受限于回调中的unchecked exception。 注意,你通常可以将这些应用程序的异常处理推迟到回调函数之后,这样,你依然可以正常使用 HibernateTemplate。 一般来说,HibernateTemplate 所提供的许多方法在许多情况下看上去更简单和便捷。 <o:p></o:p>

声明式的事务划分<o:p></o:p>

你可能感兴趣的:(spring,AOP,Hibernate,F#)