spring学习之AOP基础

来源:互联网 发布:linux apache 框架 编辑:程序博客网 时间:2024/05/16 13:52

实现接口,使用代理对象完成AOP模拟

AOP在项目中主要实现权限的控制,包括细粒度和粗粒度的区分。对那些方法实施拦截,拦截之后干什么,就是属于横切性关注点。

主要通过代理模式来实现
–静态代理
–动态代理:通过JDK或第三方框架生成字节码,如Proxy。目标对性要实现代理的接口。

代码:

  • 创建service和bean对象
package cn.gc.service;public interface PersonService {    public void save(String name);    public void update(String name, String personId);    public String getName(String personId);}
package cn.gc.service;public class PersonServiceBean implements PersonService {    //拦截所有业务方法     //判断用户是否有权限 有(user不为null)则允许执行业务方法 无则不执行业务方法    private String user = null;    public String getUser() {        return user;    }    public PersonServiceBean(String user) {        this.user = user;    }    @Override    public String getName(String personId) {        // TODO Auto-generated method stub        return "XXX";    }    @Override    public void save(String name) {        // TODO Auto-generated method stub        System.out.println("save方法");    }    @Override    public void update(String name, String personId) {        // TODO Auto-generated method stub        System.out.println("update方法");    }}
  • 代理模式创建代理对象
package cn.gc.aop;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import cn.gc.service.PersonServiceBean;/** * 代理工厂 *  * @author gc *  */public class JDKProxyFactory implements InvocationHandler {    private Object obj;    /**     * 创建代理实例,在调用代理对象的业务方法时,会被this对象所拦截     *      * @param obj     * @return     */    public Object createproxyInstance(Object obj) {        this.obj = obj;        // 在调用代理对象的业务方法时,会被this对象所拦截,而this对象通过执行invoke方法        return Proxy.newProxyInstance(this.obj.getClass().getClassLoader(),                this.obj.getClass().getInterfaces(), this);    }    /**     * 实现InvocationHandler接口的方法,把方法的调用委派给目标对象     *      * @param proxy     *            代理对象     * @param method     *            拦截到的方法     * @param args     *            传入的参数     */    @Override    public Object invoke(Object proxy, Method method, Object[] args)            throws Throwable {        PersonServiceBean beanImpl  =(PersonServiceBean)this.obj;        Object result = null;        if(beanImpl.getUser()!=null){            //用户名不为空才执行业务方法            result = method.invoke(obj, args);        }        return result;    }}
  • junit测试
package junit.test;import org.junit.BeforeClass;import org.junit.Test;import cn.gc.aop.JDKProxyFactory;import cn.gc.service.PersonService;import cn.gc.service.PersonServiceBean;public class AOPTest {    @BeforeClass    public static void setUpBeforeClass() throws Exception {    }    @Test    public void proxyTest() {        JDKProxyFactory jpf = new JDKProxyFactory();        // 代理对象要通过接口的形式来实现,因为代理对象实现了接口。        // jpf.createproxyInstance(new PersonServiceImpl("xxx"));    /*  //控制台输出        PersonService service = (PersonService) jpf        .createproxyInstance(new PersonServiceImpl("vv"));        */        //控制台不输出        PersonService service = (PersonService) jpf                .createproxyInstance(new PersonServiceBean(null));        service.save("save le ");    }}
  • 结果
    传入有参数的对象控制台会输出,传入null控制台无输出
    这里写图片描述

使用spring中cglib实现AOP功能

通过spring2.5提供的cglib的jar文件实现代理。
过程和实现JDK的思路一样 只不过工厂类变成如下的方式:

package cn.gc.aop;import java.lang.reflect.Method;import cn.gc.service.PersonServiceBean;import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;public class CGlibProxyFactory implements MethodInterceptor{    private Object obj;    /**     * 创建代理实例,在调用代理对象的业务方法时,会被this对象所拦截     *      * @param obj     * @return     */    public Object createproxyInstance(Object obj)  {        this.obj = obj;        //必须设置父类(目标类)        Enhancer enhancer = new Enhancer();        //把目标类设置为代理对象的父类,则代理对象会产生目标对象的子类,        //这个子类中会覆盖目标类中所有非final的所有方法。在覆盖的的代码中添加自身的代码        enhancer.setSuperclass(this.obj.getClass());        //设置回调方法,当代理对象的业务方法被调用的时候这个毁掉方法会被执行(就是拦截)        //要想实现这个毁掉必须要实现接口--MethodInterceptor        enhancer.setCallback(this);        return enhancer.create();    }    /**     * 回调方法     * @param proxy     *            代理对象     * @param method     *            拦截到的方法     * @param args     *            传入的参数     * @param MethodProxy 方法的代理对象     */    @Override    public Object intercept(Object arg0, Method method, Object[] args,            MethodProxy methodProxy) throws Throwable {        PersonServiceBean beanImpl  =(PersonServiceBean)this.obj;        Object result = null;        if(beanImpl.getUser()!=null){            //用户名不为空才执行业务方法            result = methodProxy.invoke(obj, args);        }        return result;    }}

一些AOP概念

–横切性关注点
AOP在项目中主要实现权限的控制,包括细粒度和粗粒度的区分。对那些方法实施拦截,拦截之后干什么,就是属于横切性关注点。

–什么是切面?
对横切性关注点的抽象的实现的过程,如上面的类就是一个切面。和类比较相似,类是对物体特征的抽象,而切面是对横切性关注点实现的过程。

–连接点
被拦截的方法。spring中连接点是方法,而其他框架中也可能是类或者构造器。

–切入点
对连接点进行拦截的定义

–通知
在拦截到连接点之后的通知,通知分前置通知,后置通知,异常通知,最终通知,环绕通知。

–目标对象
代理的目标对象 如上所例为bean对象。

–织入
将切面应用到目标对象并导致代理对象创建的过程。例如bean无法进行权限判断,但我们对他拦截 创建代理对象在应用到目标对象。

–引入
在不修改原代码的情况下,为这个类在运行期动态在这个类的代理对象创建一些方法。

1 0
原创粉丝点击