`

spring aop的实现原型模拟

 
阅读更多

我们都知道spring的配置文件中可以进行声明式事务管理,其基于的原理是spring aop 切片编程,aop是基于动态代理的,动态代理可以从jvm加载类时通过反射对方法进行额外的处理。

 

1,先定义一个接口,把我们要做的事情写成接口方法

public interface IOstocy{
   void sayHello(String name);

   void sayGoodBye(String name);

}

 2,我们给与IOstocy一个实现类

public class Ostocy implements IOstocy{
  public void sayHello(String name){
      System.out.println("hello"+name);
  }
  
  public void sayGoodBye(String name){
      System.out.println(name+"goodsBye!");
  }
}

 3,定义一个接口,用来保存你需要对IOstocy逻辑进行额外处理的方法,例如记录sayHello的对象是谁

public interface IOperation{
  void start(Method method);

  void end(Method method);

}

 定义了一个开始和结束接口方法,接下来需要给一个实现类

 

4,定义个实现类,去实现IOperation接口

public class LoggerOperation implements IOperation {

    public void end(Method method) {
        Logger.logging(Level.DEBUGE, method.getName() + " Method end .");
    }

    public void start(Method method) {
        Logger.logging(Level.INFO, method.getName() + " Method Start!");
    }

}

 

5,要写一个代理类了,这个代理类,会把IOstocy和IOperation分开处理,IOstocy中的方法是很被动的,就呆着那里,等IOperation在他随便哪个位置进来。到底从前还是后进来,就要看你自己怎么处理了,这涉及到@after @before的实现原理了。

public class DynaProxyHello implements InvocationHandler {
    /**
     * 操作者
     */
    private Object proxy;
    /**
     * 要处理的对象(也就是我们要在方法的前后加上业务逻辑的对象,如例子中的Hello)
     */
    private Object delegate;

    /**
     * 动态生成方法被处理过后的对象 (写法固定)
     * 
     * @param delegate
     * @param proxy
     * @return
     */
    public Object bind(Object delegate,Object proxy) {
        
        this.proxy = proxy;
        this.delegate = delegate;
        return Proxy.newProxyInstance(
                this.delegate.getClass().getClassLoader(), this.delegate
                        .getClass().getInterfaces(), this);
    }
    /**
     * 要处理的对象中的每个方法会被此方法送去JVM调用,也就是说,要处理的对象的方法只能通过此方法调用
    * 此方法是动态的,不是手动调用的
     */
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        Object result = null;
        try {
            //反射得到操作者的实例
            Class clazz = this.proxy.getClass();
            //反射得到操作者的Start方法
            Method start = clazz.getDeclaredMethod("start",
                    new Class[] { Method.class });
            //反射执行start方法
            start.invoke(this.proxy, new Object[] { method });
            //执行要处理对象的原本方法
            result = method.invoke(this.delegate, args);
//            反射得到操作者的end方法
            Method end = clazz.getDeclaredMethod("end",
                    new Class[] { Method.class });
//            反射执行end方法
            end.invoke(this.proxy, new Object[] { method });

        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

}

 6,测试下

public class Test {
    public static void main(String[] args) {
        IOstocy ostocy= (IOstocy)new DynaProxyHello().bind(new Ostocy(),new LoggerOperation());
        ostocy.sayGoogBye("Double J");
        ostocy.sayHello("Double J");
        
    }
}

 我的想法是在代理对象的public Object invoke(Object proxy, Method method, Object[] args)方法里面加上个if(),对传进来的method的名字进行判断,判断的条件存在XML里面.这样我们就可以配置文件时行解藕了.如果有兴趣的朋友可以把操作者,被代理者,都通过配置文件进行配置 ,那么就可以写一个简单的SpringAOP框架了.

谢谢 http://www.blogjava.net/DoubleJ/archive/2008/03/04/183796.html

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics