Spring AOP的底层实现

AOP概述

Spring AOP在运行期通过代理方式向目标类织入了增强代码。
AOP采用横向抽取机制,取代了传统纵向继承体系的重复性代码。

举例

public class UserDaoImpl implements UserDao{
	public void save(){
	checkprivilege();
	//保存用户
	...
	}
}

假设要在保存用户操作之前检查用户权限,加入一个checkprivilege方法。
事实上只需要加多几行实现代码即可。
而当有上百个DaoImpl类都需要进行该操作时,修改代码的工作量就会大得夸张。

解决方案

一、纵向继承的方法
比如为所有需要加入权限检查的类,写一个共同的父类BaseDaoImpl,如:

public class BaseDaoImpl{
	public void checkprivilege(){
		//权限检查
		...
	}
}

然后让需要加入权限检查方法的DaoImpl类去继承BaseDaoImpl类,调用父类的checkprivilege()方法即可。
二、横向抽取的方法
AOP的相关术语:
Joinpoint(连接点):可以被增强的方法;
Pointcut(切入点):真正被增强的方法;
Advice(通知):要做的事情,即权限检查;
Target(目标):被增强的对象,即UserDaoImpl;
Weaving(织入):将权限校验应用到UserDaoImpl的save方法的过程;
Proxy(代理):UserDaoImpl对象加入了权限校验方法后,会产生一个新的代理对象;
Aspect(切面):切入点和通知的组合;

1、JDK动态代理
通过JDK中类来创建Proxy代理对象。
代理类

public class MyJdkProxy implements InvocationHandler{

    private UserDao userDao;

    //构造方法获得目标对象的引用
    public MyJdkProxy(UserDao userDao){
        this.userDao = userDao;
    }

    //产生代理对象的方法
    public Object createProxy(){

        //需要获取的代理类
        Object proxy = Proxy.newProxyInstance(userDao.getClass().getClassLoader(),userDao.getClass().getInterfaces(),this);
        return proxy;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if("save".equals(method.getName())){
            //权限校验
            .......
            return method.invoke(userDao,args);
        }
        return method.invoke(userDao,args);
    }
}

对于新生成的增强UserDao的Proxy类,实现其中的save方法都相当于调用invoke方法,所以可以在invoke方法中添加权限校验的代码。
测试类:

public class SpringDemo1 {

    @Test
    public void demo1(){
        UserDao userDao = new UserDaoImpl();

        //在save之前要做一个权限的校验
        UserDao proxy = (UserDao) new MyJdkProxy(userDao).createProxy();

        proxy.save();
    }
}

2、CGlib生成代理

public class MyCglibProxy implements MethodInterceptor{

    private UserDao userDao;

    public MyCglibProxy(UserDao userDao){
        this.userDao= userDao;
    }

    public Object createProxy(){
        //1、创建核心类
        Enhancer enhancer = new Enhancer();
        //2、设置父类
        enhancer.setSuperclass(userDao.getClass());
        //3、设置回调
        enhancer.setCallback(this);
        //4、生成代理
        Object proxy = enhancer.create();
        return proxy;
    }

    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        if ("save".equals(method.getName())){
       	    //加入权限校验代码
            ......
            return methodProxy.invokeSuper(proxy,args);
        }
        return methodProxy.invokeSuper(proxy,args);
    }
}

测试类:

public class SpringDemo2 {

    @Test
    public void demo1(){
        UserDao userDao = new UserDaoImpl();

        UserDao proxy = (UserDao) new MyCglibProxy(userDao).createProxy();
        proxy.save();
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值