Spring框架 AOP (五)

来源:互联网 发布:氰化物中毒表现知乎 编辑:程序博客网 时间:2024/05/21 10:52
一、什么是AOP?
       AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。OOP引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。当我们要分散对象引入公共行为,OOP无法达到要求。
  如日志,安全、异常处理功能。日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系。
 这种散布在各处的无关的代码被称为横切(cross-cutting)代码,在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。
 所谓“方面”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来可操作性和可维护性

如果说“对象”是一个空心的圆柱体,其中封装的是对象的属性和行为;那么面向方面编程的方法,就仿佛一把利刃,将这些空心圆柱体剖开,以获得其内部的消息。而剖开的切面,也就是所谓的“方面”了。然后它又以巧夺天功的妙手将这些剖开的切面复原,不留痕迹。


使用“横切”技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。
业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。

AOP的核心思想就是“将应用程序中的商业逻辑同对其提供支持的通用服务进行分离。”


AOP的技术,主要分为两大类:
 (1)静态代理,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码
/**
 * 此处可以为接口也可以为抽象类
 * @
 *
 */
public interface Speaker{
   void say();
}
 
/**
 * 接口实现类日志功能  简单的打印一句话
 *
 *
 */
public class HelloSpeaker implements Speaker {
    public void say(){
        System.out.println("this is logger !");
    }
}
 
/**
 * 代理类实现IHelloSpeaker接口,同时拥有实际对象的引用(private HelloSpeaker helloObj;//代理类内部引用真实类)
 * 代理必须完成委托对象的动作,也可以添加自己的动作(doBefore,doAfter)。
 * 
 *
 * 
 */
public class MyProxy implements Speaker {
 
    private HelloSpeaker helloObj;// 代理类内部引用委托类
 
    public MyProxy(HelloSpeaker helloSpeaker) {
        this.helloObj = helloSpeaker;
    }
 
    private void doBefore() {
        System.out.println("method doBefore invoke!");
    }
 
    private void doAfter() {
        System.out.println("method doAfter invoke!");
 
    }
 
    @Override
    public void say() {
        doBefore();// 其他业务逻辑
        helloObj = new HelloSpeaker();
        helloObj.say();// 委托类具体的业务逻辑。
        doAfter();// 其他业务逻辑
    }
}
/**
*测试类
*/
public class TestHello {
     @Test
    public void test() {
//其中HelloProxy中helloObject为需要代理的对象,在其它地方如下来使用代理机制
        Speaker proxy = new HelloProxy(new HelloSpeaker());
        proxy.hello();
    }
}




 (2)动态代理,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
 
public class LogHandler implements InvocationHandler { 
     
 // 这是动态代理的好处,被封装的对象是Object类型,接受任意类型的对象
    private Object delegate; 


  /**
* 第1个参数是:目标类 第2个参数是:目标类接口 第3个参数是:代理目标类

* @param target
* @return
*/
     public Object bind(Object delegate) { 
        this.delegate = delegate; 
        return Proxy.newProxyInstance( 
                           delegate.getClass().getClassLoader(), 
                           delegate.getClass().getInterfaces(), 
                           this); 
       }
 
 
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        Object result = null;         
        try { 
            System.out.println("method starts..."+method);
            result = method.invoke(delegate, args);//动态代理
            System.out.println("method starts..."+method);
        } catch (Exception e){ 
            e.printStackTrace();
        }        
        return result; 
    }
}
//测试程序
   @Test
    public void test() {
        LogHandler logHandler  = new LogHandler(); 
         
       Speaker helloProxy =  (Speaker) logHandler.bind(new HelloSpeaker()); 
        helloProxy.say();
    }


二、AOP使用在那些方面
 Authentication 权限
 Caching 缓存
 Context passing 内容传递
 Error handling 错误处理
 Lazy loading 懒加载
 Debugging  调试
 logging, tracing, profiling and monitoring 记录跟踪 优化 校准
 Performance optimization 性能优化
 Persistence  持久化
 Resource pooling 资源池
 Synchronization 同步
 Transactions 事务


三、AOP相关概念介绍


  切面(aspect):用来切插业务方法的类。

  连接点(joinpoint):是切面类和业务类的连接点,其实就是封装了业务方法的一些基本属性,作为通知的参数来解析。

  通知(advice):在切面类中,声明对业务方法做额外处理的方法。

  切入点(pointcut):业务类中指定的方法,作为切面切入的点。其实就是指定哪个方法作为切面。

  目标对象(target object):被代理对象。

  AOP代理(aop proxy):代理对象。
 
 通知:
  前置通知(before advice):在切入点之前执行。

  后置通知(after returning advice):在切入点执行完成后,执行通知。

  环绕通知(around advice):包围切入点,调用方法前后完成自定义行为。

  异常通知(after throwing advice):在切入点抛出异常后,执行通知。
0 0