Spring面向切面编程之AOP代理模式

代理模式:proxy,surrogate,在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
Spring aop的面向切面进行开发,实现的原理就是使用动态代理设置模式。

一,代理设置模式

jdk:静态代理,动态代理(非常常用)。
cglib生成的动态代理。

二,jdk静态代理

例,首先创建singer 歌手接口

public interface Singer {
    //唱歌接口,跳舞接口
    public  void   singing();
    public  void   danceing();
}

创建一个王宝强,为歌手实现类:

public class wangBaoQiang implements Singer{

    @Override
    public void singing() {
        System.out.println("正在唱歌");
    }

    @Override
    public void danceing() {
        System.out.println("正在跳舞");
    }
}

再创建一个代理对象(经纪人):

//代理对象
//首先代理对象也要实现接口
//也要调用王宝强(目标对象的方法)
public class ProxyWang implements Singer{
private  Singer singer;

    public ProxyWang(Singer singer) {
        this.singer = singer;
    }

    @Override
    public void singing() {
        System.out.println("舞台搭建成功");
        singer.singing();
    }

    @Override
    public void danceing() {
        System.out.println("请开始跳舞");
        singer.danceing();
    }
}

创建test类

首先实例化对象是王宝强(目标对象)
        Singer singer=new wangBaoQiang();
        //实例化代理对象来调用其方法,在目标对象前后做一些相关操作
        ProxyWang proxyWang=new ProxyWang(singer);
        proxyWang.singing();

其结果为

舞台搭建成功
正在唱歌

静态代理:优点 好理解,
缺点:扩展性差,每次生成的只要有不同类,即使操作一样,也要重新生成一个代理对象。

三,jdk动态代理。

首先新增一个明星 孙笑川;

public class SunXiaoChuan implements  Singer{
    @Override
    public void singing() {
        System.out.println("孙哥正在唱歌");
    }

    @Override
    public void danceing() {
        System.out.println(
                "孙哥正在跳舞"
        );
    }
}

设置代理:

//实现动态代理
public class ProxyAi  implements InvocationHandler {

    private  Object object;
    //构造函数 用到的object
    public  ProxyAi( Object object){
        this.object=object;
    }

//重写的方通过只要你调用目标对象方法,都会走
    //第一个参数是你的代理对象,第二个参数是你调用目标对象的方法(通过反射来实现)
    //第三个参数是你调用对象的方法用的参数,
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //这个参数 invoke就是通过反射来调用目标对象的方法,第一个参数是你要调用目标对象方法的类
        //第二个参数是你要调用目标对象方法的参数
        Object O=null;
        if(method.getName().equals("singing")){
            System.out.println("搭建舞台,市场成功");
            O= method.invoke(object,args);
            System.out.println("唱歌结束");
        }else if(method.getName().equals("danceing")){
            System.out.println("可以跳舞");
            O= method.invoke(object,args);
            System.out.println("演出结束");
        }

        return null;
    }
}

在text中使用动态代理
jdk提供了这样一个类,代理的意思
第一个参数叫类加载器,
第二个参数是目标对象的class,注意是类的.class
第三个参数是代理对象

Singer singer=new SunXiaoChuan();
        //jdk提供了这样一个类,代理的意思
        //第一个参数叫类加载器,
        // 第二个参数是目标对象的class,注意是类的.class
        //第三个参数是代理对象
        //返回值为object,这里强转为了singer类
       Singer singer1= (Singer) Proxy.newProxyInstance(
                singer.getClass().getClassLoader(),
               new Class[]{Singer.class},
               new ProxyAi(singer));

        singer1.singing();
        singer1.danceing();

结果为

搭建舞台,市场成功
孙哥正在唱歌
唱歌结束
可以跳舞
孙哥正在跳舞
演出结束

四,cglib生成的动态代理。

首先导包,并buiding path,
在这里插入图片描述

创建cgLibProxy,实现MethodInterceptor

public class CgLibProxy implements MethodInterceptor {
//MethodInterceptor  方法拦截器
    //第一个参数是你的代理对象,
    //第二个参数是你的目标对象的方法
    //第三个参数是你的目标对象的方法参数
    //第四个是你代理对象拦截方法的对象
    
    //先实例化对象
    private  Object object;
    //创建代理对象,也可以用set方法
    public  Object getCgLibProxy(Object object){
        this.object=object;
        //得到创建代理对象的对象,enhancer都是jar内封装好的
        Enhancer enhancer =new Enhancer();
        //设置类加载器
        enhancer.setClassLoader(this.object.getClass().getClassLoader());
        //设置其父类
        enhancer.setSuperclass(this.object.getClass());
        //设置回调,只要走下面这个方法都会走回调
        enhancer.setCallback(this);
        //创建代理对象
        return  enhancer.create();
    }
    //这个方法就是在调用目标对象的方法都会执行这个方法

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("先彩排唱歌");
        Object ob=  method.invoke(object, objects);
        return ob;
    }
}

text中:

  //实例化一个cglibproxy 代理对象这个类
        //这个参数代表我们的目标对象
        CgLibProxy cgLibProxy=new CgLibProxy();
       Singer singer= new wangBaoQiang();
      Singer singer2= (Singer) cgLibProxy.getCgLibProxy(singer);
    singer2.singing();
    }

结果为:

先彩排唱歌
正在唱歌

五,小结

动态代理:利用java的反射来实现。非常常用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值