面向切面编程AOP

创作人 Leo


编辑时间 Wed Jan 1,2020 at 10:13


面向切面编程AOP

面向切面编程 AOP 为 OOP 的一种扩展

场景:

一个应用在某些操作需要加如日志功能

传统的oop做法为在每一个操作中加上日志功能,其实也可以单独写一个日志类,但这样就使业务类和日志类强关联了,就不够OO了

AOP提供了一种思想,将日志这种碎片功能以切面(在一个业务逻辑中插入一个小块)的方式插入到需要的操作中

java的实现是使用代理Proxy类实现

Proxy:

在网上摘抄了一段java代理的解释

1.什么是动态代理?

答:动态代理可以提供对另一个对象的访问,同时隐藏实际对象的具体事实。代理一般会实现它所表示的实际对象的接口。代理可以访问实际对象,但是延迟实现实际对象的部分功能,实际对象实现系统的实际功能,代理对象对客户隐藏了实际对象。客户不知道它是与代理打交道还是与实际对象打交道。

2.为什么使用动态代理?

答:因为动态代理可以对请求进行任何处理

3.使用它有哪些好处?

答:因为动态代理可以对请求进行任何处理

4.哪些地方需要动态代理?

答:不允许直接访问某些类;对访问要做特殊处理等

具体做法就是在代理中invoke实际功能函数的前后加入碎片功能,也就是我们需要实现的切面

示例java代码:

首先编写我们的业务接口(StudentInfoService.java)

public interface StudentInfoService{
    void findInfo(String studentName);
}

及其实现类(StudentInfoServiceImpl.java)

public class StudentInfoServiceImpl implements StudentInfoService{
    public void findInfo(String name){
        System.out.println("你目前输入的名字是:"+name);
    }
}

处理拦截目的的类(MyHandler.java)

import org.apache.log4j.Logger;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.lang.reflect.Method;
public class MyHandler implements InvocationHandler{
    private Object proxyObj;
    private static Logger log=Logger.getLogger(MyHandler.class);
 
    public Object bind(Object obj){
        this.proxyObj=obj;
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),this);
    }
 
    public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{
        Object result=null;
        try{
            //请在这里插入代码,在方法前调用
            ("调用log日志方法"+method.getName());
            result=method.invoke(proxyObj,args); //原方法
            //请在这里插入代码,方法后调用
        }catch(Exception e){
            e.printStackTrace();
        }
        return result;
    }
}

我们实现一个工厂,为了方便我们使用该拦截类(AOPFactory.java)

public class AOPFactory{
 
    private static Object getClassInstance(String clzName){
        Object obj=null;
        try{
            Class cls=Class.forName(clzName);
            obj=(Object)cls.newInstance();
        }catch(ClassNotFoundException cnfe){
            System.out.println("ClassNotFoundException:"+cnfe.getMessage());
        }catch(Exception e){
            e.printStackTrace();
        }
        return obj;
    }
 
    public static Object getAOPProxyedObject(String clzName){
        Object proxy=null;
        MyHandler handler=new MyHandler();
        Object obj=getClassInstance(clzName);
        if(obj!=null) {
            proxy=handler.bind(obj);
        }else{
            System.out.println("Can't get the proxyobj");
            //throw
        }
        return proxy;
    }
}

基本的拦截与其工厂我们都实现了,现在测试(ClientTest.java)

public class ClientTest{
    public static void main(String[] args){
        StudentInfoService studentInfo= (StudentInfoService)AOPFactory.getAOPProxyedObject("StudentInfoServiceImpl");
        studentInfo.findInfo("阿飞");
    }
}

php 可以通过反射的形式实现一个面向切面的程序

示例PHP代码:

<?php
 
/**
 * Class Person
 * 业务类
 */
class Person{
 
    function say( $content ) {
        echo $content , "<br />" ;
    }
 
}
 
/**
 * Class Log
 * 日志工具类
 */
class Log{
 
    public static $_L_ERR = 1 ;
    public static $_L_NOTICE = 2 ;
 
    public static function write($content, $level=null){
        if ($level == null)
            $level = self::$_L_NOTICE ;
 
        echo 'level = ' . $level . ', content is '. $content ;
    }
 
}
 
/**
 * Class Handler
 * 代理句柄
 */
class ProxyHandler{
 
    private $obj ;
    private $_obj ;
 
    public function __construct( $class )
    {
        $this->obj = new ReflectionClass($class) ;
        $this->_obj = new $class();
    }
 
 
    public function __call($name, $arguments)
    {
        // TODO: Implement __call() method.
 
        //  在这里插入碎片程序
        Log::write("这里插入碎片程序,比如日志 <br />");
 
        $method = $this->obj->getMethod($name) ;
        $r = $method->invokeArgs($this->_obj, $arguments);
 
        //  或者在这里插入碎片程序
 
        return $r ;
    }
 
}
 
/**
 * Class AopFactory
 * 切面代理工厂
 */
class AopFactory{
 
    public static function getProxy($class){
        if (!is_string($class)){
            throw new Exception('require a class name') ;
        }
 
        return new ProxyHandler($class) ;
    }
 
}
 
 
$p1 = AopFactory::getProxy('Person') ;
$p1->say('hello');
 
 
?>


阅读:946
搜索
  • Linux 高性能网络编程库 Libevent 简介和示例 2557
  • Mac系统编译PHP7【20190929更新】 2290
  • zksync 和 layer2 2190
  • web rtc 学习笔记(一) 2172
  • Hadoop 高可用集群搭建 (Hadoop HA) 2160
  • Hadoop Map Reduce 案例:好友推荐 2104
  • react 学习笔记(一) 2065
  • Linux 常用命令 2056
  • 小白鼠问题 2040
  • 安徽黄山游 2037
简介
不定期分享软件开发经验,生活经验