Spring理论基础-面向切面编程

AOPAspect-Oriented Programming的缩写,中文翻译是面向切面编程。做为Spring的特征之一,是要好好学习的。git

首先面向切面编程这个名称很容易让人想起面向对象编程(OOP)来。咱们知道面向对象编程是从上往下的把系统拆分红若干个类,如Web项目中常见的ControllerServiceDao等分层。可是面向对象编程对于从左到右的水平抽象十分无力,相似于日志、权限等系统级功能的代码会重复的出如今任何地方。简单的说,面向切面编程是对面向对象编程的一种补充,它能够把系统里一些分散的重复代码集中在一块儿,抽象成一个切面。先来举一个例子:github

有一个内部使用的管理系统,Controller中的每一个接口在调用时都要记录下当前用户名称、当前时间等参数。编程

很明显这个需求的实现代码在每一个接口中都是重复的。即便提取成公共类的公共方法,在每一个接口里也都有一句该公共方法的调用,致使类之间的耦合。bash

接口流程图

咱们但愿把原来接口中的记录代码去除掉,使这些接口只关注本身的业务逻辑。而后使用预编译或运行期动态代理等方式实如今不修改接口代码的状况下,为接口添加记录功能。这种动态地将代码织入到类的指定方法、指定位置上的编程思想就是面向切面编程。markdown

接口流程图(添加AOP)

概念

面向切面编程具体的一些概念。ide

《EXPERT ONE ON ONE J2EE DEVELOPMENT WITHOUT EJB》第8章、《Spring实战》第4章:oop

  • 加强(advice,另译为通知,但《Spring3.x企业应用开发实战》做者不同意):在特定链接点执行的动做。例子中的实现代码就是加强。学习

  • 切点(pointcut):一组链接点的总称,用于指定某个加强应该在什么时候被调用。例子中的指定哪些接口和指定位置就是切点。ui

  • 链接点(join point):在应用执行过程当中可以插入切面的一个点。例子中具体的一个接口和指定位置的结合就是链接点。this

  • 切面(aspect):通知(即加强)和切点的结合。

AOPSpring中主要是经过动态代理实现的,具体实现也分为两种:JDK动态代理CGLIB动态代理。其中JDK动态代理是基于接口代理,CGLIB动态代理是基于继承代理。

JDK动态代理

做为Java自带的一种动态代理技术,JDK动态代理的优点是使用反射技术来生成代理类,在生成效率上比较高。缺点是只能基于接口来动态代理,若是目标类没有实现任何接口是不能使用JDK动态代理的。

来看一个用JDK动态代理的例子。

public class DynamicProxy implements InvocationHandler {

    /**
     * 被代理类
     */
    private Object target;

    public DynamicProxy(Object target) {
        this.target = target;
    }

    public static Object bind(Object target) {
        InvocationHandler invocationHandler = new DynamicProxy(target);
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), invocationHandler);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println(method.getName() + " 方法执行前");
        //执行被代理类方法
        Object ret = method.invoke(target, args);
        System.out.println(method.getName() + " 方法执行后");
        return ret;
    }

    public static void main(String[] args) {
        Dao dao = new OrderDao();
        dao.doSomeThing();
        Dao daoProxy = (Dao) DynamicProxy.bind(dao);
        daoProxy.doSomeThing();
    }

}
复制代码
public class OrderDao implements Dao {

    @Override
    public void doSomeThing() {
        System.out.println("test");
    }

}
复制代码
public interface Dao {

    void doSomeThing();

}
复制代码
输出:
test
doSomeThing 方法执行前
test
doSomeThing 方法执行后

Process finished with exit code 0
复制代码

后记

此次只是梳理下概念,把本身理解的AOP概念写下来。也参考了不少文章,大致都是一致的细节上有些不一样,把本身理解的写出来给你们看下就知道有没有错了。顺便整理一下,省得之后别人问起本身支支吾吾的不知道从哪提及。并无去了解Spring中具体的AOP实现,有兴趣的同窗能够自行深刻了解下。

个人博客地址

参考资料

什么是面向切面编程AOP?

好书一块儿读(115):重学Spring之面向切面

相关文章
相关标签/搜索