利用java 的动态代理模拟spring的AOP

AOP

AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善。OOP允许开发者定义纵向的关系,但并不适合定义横向的关系,例如日志功能。平常我门需要记录一些操作的日志,需要在操作的业务逻辑代码里嵌入日志模块的代码。这些日志模块的代码与操作的代码逻辑无关,只是做一个记录,而且在其它的操作模块里也都有类似的一段日志记录的代码。这种散布在各处的无关的代码被称为横切(cross cutting),在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。

AOP技术的解决

AOP技术利用一种称为”横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为”Aspect”,即切面。所谓”切面”,简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。

使用”横切”技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处基本相似,比如权限认证、日志、事物。AOP的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。

例子

例如 有个吃午餐和吃晚餐的业务逻辑,现在要记录 吃晚餐和吃午餐的吃饭开始时间日志,那么普通的情况下我门是在吃午餐的记录个日志,在吃晚餐记录个日志,但是利用aop 的话就是在吃饭的前面 切上一刀, 做一个切面, 切面和 吃晚餐 吃午餐 业务线交接的地方就是切入点

这里写图片描述

模拟开始

说了那么多aop 现在开始使用java 的动态代理模拟一个简单的aop。

动态代理就是生成一个代理对象,代理需要被代理的对象。 代理对象 是为了 代理被代理对象创建的对象。好了说的有点绕动态代理有 一个代理对象,和一个被代理对象。 代理对象是每次调用代理的时候动态生成的所以叫做动态代理。

背景

我门有一个业务逻辑模块 UserService 和一个 实体类 User 还有一个持久层模块 UserDAO 和它的实现 UserDAOImpl。
他们之间 UserService 调用(依赖)UserDAO 来操作数据库。我门

在test 中运行的时候呢要创建 UserService 和 UserDAO 并将 UserDAO set 到 UserService 中,这是我门正常的逻辑。
这部分代码参考: http://blog.csdn.net/u012373815/article/details/74937913

代码时刻

我门创建一个动态代理的类


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * Created by yangyibo on 17/7/6.
 */
public class LogInterceptor implements InvocationHandler {
    /**
     * target 被代理对象,可以通过参数传进来
     */
    private Object target ;

    public Object getTarget() {
        return target;
    }

    public void setTarget(Object target) {
        this.target = target;
    }

    //在执行被代理对象的方法前执行的方法,我门要切进去的逻辑
    public void beforeMethod(Method m) {
        System.out.println(m.getName()+"  begin ..........");
    }


    public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
        //执行我门的逻辑
        beforeMethod(m);
        //调用被代理对象的方法
        m.invoke(target, args);
        return null;
    }
}

然后在test 中使用这个动态代理

 //通过jdk 的动态代理实现
    @Test
    public void testProxy() {
        //被代理对象
        UserDAO userDAO = new UserDAOImpl();
        LogInterceptor li = new LogInterceptor();
        li.setTarget(userDAO);
        //newProxyInstance 产生一个代理对象 ,三个参数
        //1.classloader 代理对象和被代理对象应该处于同一个 classloader
        //2.接口 产生的代理对象应该实现那些接口
        //3.handel 执行代理对象方法时,应用那个handel 处理。
        //(接口中有什么方法,代理中就有什么方法 代理中的每个方法在调用的时候都会把 方法自身传给 handel, 并把 代理对象和参数都传递过去 )
  UserDAO userDAOProxy = (UserDAO) Proxy.newProxyInstance(userDAO.getClass().getClassLoader(), userDAO.getClass().getInterfaces(), li);

        System.out.println(userDAOProxy.getClass());
        userDAOProxy.detele();
        userDAOProxy.save(new User());
     }

解析:userDAO 是被代理对象, userDAOProxy是动态生成的代理对象。userDAO 把自己的ClassLoader 和自己实现的接口 还有InvocationHandler。

动态生成的代理对象实现了被代理对象的接口,接口中有什么方法,代理中就有什么方法 代理中的每个方法在调用的时候都会把 方法自身传给 handel, 并把 代理对象和参数都传递过去。

在spring中如果你的类没有实现接口,spring 也能给你生成动态代理,spring直接生成二进制码,用继承。 

在上述例子中 LogInterceptor 的 beforeMethod 就相当于 aop 的advice 和 Aspect 切面类

userDAO 就相当于 target,save方法就相当与切入点。

说的不是很清楚,忘谅解。十分抱歉

好了完整代码请点击:
https://github.com/527515025/mySpring.git
参考:
http://www.cnblogs.com/xrq730/p/4919025.html

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值