spring代理

一、代理模式:
代理模式的英文叫做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方法就是代理类的方法体,使用字节码增强机制创建代理对象的.

猜你喜欢

转载自blog.csdn.net/weixin_42772943/article/details/82987518