spring代理

本文介绍了Java代理模式的两种实现方式:静态代理和动态代理。重点讲解了JDK动态代理和CGLIB代理的工作原理、优缺点,以及在Spring中的应用。静态代理存在代码重复和不易维护的问题,而动态代理则通过反射和接口实现动态创建代理类,JDK动态代理需基于接口,CGLIB代理则无需接口,通过子类化目标类实现。

一、代理模式:
代理模式的英文叫做Proxy或Surrogate,中文都可译为”代理“,所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动。在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
(1).静态代理:

    Singer singer=new WangBao();

    ProxyWang proxyWang=new ProxyWang(singer);

    proxyWang.singing();
    总结:

ProxyWang 是静态代理类,WangBao是目标对象类,都实现了Singer 是接口,
1、静态代理模式并没有做到事务的重用
2、假设dao有100个类,100个proxy,接口中有多少方法,在proxy层就得实现多少方法,有多少方法就要开启和提交多少事务
3、如果一个proxy实现了多个接口,如果其中的一个接口发生变化(添加了一个方法),那么proxy也要做相应改变

(2)动态代理:
动态代理类:在程序运行时,运用反射机制动态创建而成。

JDK的动态代理必须具备四个条件:1、目标接口 2、目标类 3、拦截器 4、代理类
Singer singer=new XueZhiQian();
//jdk提供了一个类–第一个参数是类加载器,第二个参数是目标对象的class的实现接口,第三个参数是代理对象

   Singer singer1 = (Singer) Proxy.newProxyInstance(singer.getClass().getClassLoader()
            , singer.getClass().getInterfaces(), new ProxyAi(singer));
            singer1.singing();
            package com.offcn.text;

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

  • 动态代理类jdk

  • */
    public class ProxyAi implements InvocationHandler{
    private Object object;

    public ProxyAi(Object object) {
    this.object = object;
    }

    //只要你的调用目标对象的方法都会走这个方法
    //第一个参数是你的代理对象,第二参数是你调用目标对象的方法(反射)
    //第三个参数是你调用目标对象的方法里的参数
    @Override
    public Object invoke(Object o, Method method, Object[] args) throws Throwable {
    //第一个参数是调用目标对象的方法的类,第二参数是你要调用目标对象方法的参数
    Object mm=null;
    if (method.getName().equals(“singing”)){
    System.out.println(“唱歌试唱成功”);
    mm = method.invoke(object, args);
    System.out.println(“唱歌wang”);

      }else if (method.getName().equals("dancing")){
          System.out.println("dancing成功");
          mm = method.invoke(object, args);
          System.out.println("dancingover");
      }
    
    
      return mm;
    

    }
    }
    优点:
    1、因为利用JDKProxy生成的代理类实现了接口,所以目标类中所有的方法在代理类中都有。
    2、生成的代理类的所有的方法都拦截了目标类的所有的方法。而拦截器中invoke方法的内容正好就是代理类的各个方法的组成体。
    3、利用JDKProxy方式必须有接口的存在。
    4、invoke方法中的三个参数可以访问目标类的被调用方法的API、被调用方法的参数、被调用方法的返回类型。
    缺点:
    1、在拦截器中除了能调用目标对象的目标方法以外,功能是比较单一的,在这个例子中只能处理事务
    2、拦截器中的invoke方法的if判断语句在真实的开发环境下是不靠谱的,因为一旦方法很多if语句需要写很多。

(3).cglib代理:
前提先导入Cglib代理的jar包
package com.offcn.text;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;

public class CglibProxy implements MethodInterceptor {
private Object object;

public Object getCglibProxy(Object object) {
    this.object = object;
    //创建或引入jar包中代理对象
    Enhancer enhancer=new Enhancer();
    //设置内加载器
    enhancer.setClassLoader(this.object.getClass().getClassLoader());
    //设置其父类
    enhancer.setSuperclass(this.object.getClass());
    //设置回调   只要走下面这个方法都会走回调
    enhancer.setCallback(this);
    //创建代理对象
    return enhancer.create();
}
/*
* MethodInterceptor--方法拦截器
* */
@Override
//这个方法就是你调用目标对象的方法都会执行这个方法
//第一个参数是你的目标对象的代理对象,第二个参数也是目标对象的方法,第三个参数是目标对象的方法参数
//第四个参数是你代理对象拦截方法的对象
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
    System.out.println("sucesssful");
   Object obj= method.invoke(object,args);

    return null;
}

}

//实例化一个cglibProxy代理对象
CglibProxy cglibProxy=new CglibProxy();
Singer singer=new WangBao();
//参数代表目标对象singer
Singer singer1 =(Singer)cglibProxy.getCglibProxy(singer);
singer1.singing();

总结:
1、CGlib是一个强大的,高性能,高质量的Code生成类库。它可以在运行期扩展Java类与实现Java接口。
2、用CGlib生成代理类是目标类的子类。
3、用CGlib生成 代理类不需要接口
4、用CGLib生成的代理类重写了父类的各个方法。
5、拦截器中的intercept方法内容正好就是代理类中的方法体 CGLIB和JDK动态代理区别:

JDK:
目标类和代理类实现了共同的接口
拦截器必须实现InvocationHandler接口,而这个接口中invoke方法体的内容就是代理对象方法体的内容
CGLIB:
目标类 是代理类的父类
拦截器必须实现MethodInterceptor接口,而接口中的intercept方法就是代理类的方法体,使用字节码增强机制创建代理对象的.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值