博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring-aop(一)
阅读量:4983 次
发布时间:2019-06-12

本文共 5091 字,大约阅读时间需要 16 分钟。

写一个计算类,计算前后需要打印日志。

interface ArithmeticCalculator {    public int add(int i, int j);    public int sub(int i, int j);    public int mul(int i, int j);    public int div(int i, int j);}

 

public class ArithmeticCalculatorImpl implements ArithmeticCalculator {    @Override    public int add(int i, int j) {        // TODO Auto-generated method stub        System.out.println("The method add begins with[" + i + "," + j + "]");        int result = i + j;        System.out.println("The method add ends with " + result);        return result;    }    @Override    public int sub(int i, int j) {        // TODO Auto-generated method stub        System.out.println("The method sub begins with[" + i + "," + j + "]");        int result = i - j;        System.out.println("The method sub ends with " + result);        return result;    }    @Override    public int mul(int i, int j) {        // TODO Auto-generated method stub        System.out.println("The method mul begins with[" + i + "," + j + "]");        int result = i * j;        System.out.println("The method mul ends with " + result);        return result;    }    @Override    public int div(int i, int j) {        // TODO Auto-generated method stub        System.out.println("The method div begins with[" + i + "," + j + "]");        int result = i / j;        System.out.println("The method div ends with " + result);        return result;    }}

从上面代码可以看出,四个方法的日志有重复的部分。

 

Main.java

public class Main {    public static void main(String[] args) {        // TODO Auto-generated method stub        ArithmeticCalculator arithmeticCalculator = null;        arithmeticCalculator = new ArithmeticCalculatorImpl();                int result = arithmeticCalculator.add(1, 2);        System.out.println("-->" + result);                result = arithmeticCalculator.div(4, 2);        System.out.println("-->" + result);    }}

 

打印结果:

The method add begins with[1,2]The method add ends with 3-->3The method div begins with[4,2]The method div ends with 2-->2

结果没什么问题,可是在加入日志后,原有的业务方法急剧膨胀,每个方法在处理核心逻辑的同时还要兼顾其他多个关注点,并且在日志需求发生变化时,必须修改所有模块。

 

接下来,我们使用动态代理解决上述问题

代理设计模式的原理:使用一个代理将对象包装起来,然后用该代理对象取代原始对象,任何对原始对象的调用都要通过代理。代理对象决定是否以及何时将方法调用转到原始对象上。

public class ArithmeticCalculatorImpl implements ArithmeticCalculator {    @Override    public int add(int i, int j) {        // TODO Auto-generated method stub        int result = i + j;        return result;    }    @Override    public int sub(int i, int j) {        // TODO Auto-generated method stub        int result = i - j;        return result;    }    @Override    public int mul(int i, int j) {        // TODO Auto-generated method stub        int result = i * j;        return result;    }    @Override    public int div(int i, int j) {        // TODO Auto-generated method stub        int result = i / j;        return result;    }}

 

public class ArithmeticCalculatorLoggingProxy {        private ArithmeticCalculator target;    public ArithmeticCalculatorLoggingProxy(ArithmeticCalculator target) {        super();        this.target = target;    }    public ArithmeticCalculator getLoggingProxy() {        ArithmeticCalculator proxy = null;        //代理对象由哪一个类加载器负责加载        ClassLoader loader = target.getClass().getClassLoader();        //代理对象的类型,即其中有哪些方法        Class [] interfaces = new Class[]{ArithmeticCalculator.class};        //当调用代理对象其中的方法时,该执行的代码        InvocationHandler h = new InvocationHandler() {            /**             * proxy: 正在返回的那个代理对象,一般情况下,在invoke方法中都不使用对象             * method: 正在被调用的方法             * args: 调用方法时,传入的参数             */            @Override            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {                // TODO Auto-generated method stub                String methodName = method.getName();                //日志                System.out.println("The methods " + methodName + " begins with" + Arrays.asList(args));                //执行方法                Object result = method.invoke(target, args);                //日志                System.out.println("The methods " + methodName + " ends with" + result);                return result;             }        };        proxy = (ArithmeticCalculator) Proxy.newProxyInstance(loader, interfaces, h);        return proxy;    }}

Main.java

     ArithmeticCalculator target = new ArithmeticCalculatorImpl();        ArithmeticCalculator proxy = new ArithmeticCalculatorLoggingProxy(target).getLoggingProxy();                int result = proxy.add(1, 2);        System.out.println("-->" + result);                result = proxy.div(4, 2);        System.out.println("-->" + result);

打印结果:

The methods add begins with[1, 2]The methods add ends with3-->3The methods div begins with[4, 2]The methods div ends with2-->2

 

用了动态代理方法,就会发现ArithmeticCalculatorImpl实现类变得清洁很多。并且日志被封装在invoke方法中,修改十分方便。

 

aop术语:

切面:横切关注点(跨越应用程序多个模块的功能)被模块化的特殊对象

通知:切面必须要完成的工作

目标:被通知的对象

代理:向目标对象应用通知之后创建的对象

连接点:程序执行的某个特定位置,如类某个方法调用前,调用后,方法抛出异常后

由两个信息确定:方法表示的程序执行点,想对点表示的方位。

切点:每个类都拥有多个连接点,即连接点是程序类中客观存在的事务。

AOP通过切点定位到特定的连接点:类比:连接点相当于数据库中的记录,切点相当于查询条件。

 

前置通知:

 

转载于:https://www.cnblogs.com/X-Spider/p/5395687.html

你可能感兴趣的文章
主题演讲:未来新趋势电动车
查看>>
常用DNS列表(电信、网通)
查看>>
LeetCode-178:分数排名
查看>>
转:退火算法 Simulate Anneal Arithmetic (SAA,模拟退火算法)
查看>>
Django电商项目---完成商品主页显示day2
查看>>
如何解决文章格式化编辑器win7 64位下找不到Comctl32.ocx
查看>>
核心动画-翻页效果的实现
查看>>
微信小程序弹出框 页面依然可以滑动的解决
查看>>
$.ajax同域请求,跨域请求的解决方案
查看>>
octave操作
查看>>
【Python】安装Python的mysql模块
查看>>
layui中的html怎样接收后台的值,layui框架与SSM前后台交互的方法
查看>>
Skulpt在线模拟运行Python工具
查看>>
287.软件测试概述
查看>>
297.白盒测试
查看>>
新闻客户端的突破与创新
查看>>
网络通信引擎ICE的使用
查看>>
js滚动事件实现滚动触底加载
查看>>
CetnOS minimal 网络不可用
查看>>
MySQL 数据库备份
查看>>