代理模式

静态代理模式

  • 概念

静态代理需要被代理类,代理类,接口
将被代理类包一层
一个被代理的类和接口
代理类实现该接口并且包含被代理类
代理类在被代理的方法上进行扩展

//接口
interface 新娘{
    void 洞房();
}
//被代理类
class 马蓉 implements 新娘{
   @Override
   public void 洞房(){
        输出一条信息
   }
}
//代理类
class 王宝强 implements 新娘{
    private Object obj;//必须是实现了新娘的类
    public 王宝强(Object obj){
        this.obj = obj;
    }
    @Override
    public void 洞房(){
        先拜堂;
        obj.洞房();
   }
}
//调用代理者
class 客户端{
    main(){
      马蓉 小马蓉 =  new 马蓉();(生成出一个被代理的类)
      王宝强 小王宝强 =  new 王宝强(小马蓉);(将代理者生存出来,此时要将代理者传入)
      小王宝强.洞房();
    }
}
  • 缺点

要代理的类必须实现一个接口
要代理的类中的方法必须要在接口中才能被调用

动态代理原理

通过对原类进行继承,生成类代码编译成class,加载到内存中

public interface CustomInvocationHandler {
    public Object invoke(Object proxy, Method method,Object[] args) throws Throwable;
}

public class CustomClassLoader extends ClassLoader{
    private File baseDir;

    public CustomClassLoader(){
        String basePath = CustomClassLoader.class.getResource("").getPath();
        this.baseDir = new File(basePath);

    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        String className = CustomClassLoader.class.getPackage().getName() + "." + name;
        if (baseDir != null){
            String clzzName = name.replaceAll("\\.", "/") + ".class";
            File classFile = new File(baseDir, clzzName);
            if(classFile.exists()){
                FileInputStream in =null;
                ByteArrayOutputStream out = null;

                try {
                    in = new FileInputStream(classFile);
                    out = new ByteArrayOutputStream();
                    byte[] bytes = new byte[1024];
                    int len;
                    while ((len = in.read(bytes)) != -1){
                        out.write(bytes,0,len);
                    }
                    return defineClass(className,out.toByteArray(),0,out.size());
                } catch (Exception e) {
                    e.printStackTrace();
                }finally {
                    if (null != in){
                        try {
                            in.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    if (null != out){
                        try {
                            out.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
        return null;
    }
}

package com.lon.lin;

import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class CunstomProxy {
    private static final String ln = "\r\n";

    public  static Object newInstance(CustomClassLoader classLoader,Class<?>[] classes,CustomInvocationHandler h ){


        try {
            String src = generateSrc(classes[0]);
            String path = CunstomProxy.class.getResource("").getPath();
            File file = new File(path + "$Proxy0.java");
            FileWriter fileWriter = new FileWriter(file);
            fileWriter.write(src);
            fileWriter.flush();
            fileWriter.close();

            JavaCompiler systemJavaCompiler =ToolProvider.getSystemJavaCompiler();
            StandardJavaFileManager standardFileManager = systemJavaCompiler.getStandardFileManager(null, null, null);
            Iterable<? extends JavaFileObject> javaFileObjects = standardFileManager.getJavaFileObjects(file);
            JavaCompiler.CompilationTask task = systemJavaCompiler.getTask(null, standardFileManager, null, null, null, javaFileObjects);
            task.call();
            standardFileManager.close();

            Class<?> proxyClass = classLoader.findClass("$Proxy0");
            Constructor<?> constructor = proxyClass.getConstructor(CustomInvocationHandler.class);
            return constructor.newInstance(h);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return  null;


    }

    private static String generateSrc(Class<?> classes) {
        StringBuilder sb = new StringBuilder();
        sb.append("package com.lon.lin;"+ln);
        sb.append("import java.lang.reflect.Method;" + ln);
        sb.append("public class $Proxy0 implements "+classes.getName() +" {"+ln);
        sb.append("CustomInvocationHandler h;"+ln);
        sb.append("public $Proxy0(CustomInvocationHandler h) {"+ln);
        sb.append("this.h = h;"+ln);
        sb.append("}");

        for (Method method:classes.getMethods()){
            sb.append("public "+method.getReturnType().getName()+" "+method.getName()+"(){"+ln);
            sb.append("try{"+ln);
            sb.append("Method m = "+classes.getName()+".class.getMethod(\""+method.getName()+"\",new Class[]{});"+ln);
            sb.append("this.h.invoke(this,m,null);"+ln);
            sb.append("}catch(Throwable e){e.printStackTrace();}"+ln);
            sb.append("}"+ln);

        }
        sb.append("}");
        return sb.toString();
    }
}

public class MuMu implements Person {

    @Override
    public void shopping() {
        System.out.println("我喜欢购物");
    }
}


public interface Person {

    public void shopping();
}


public class TaoBao implements  CustomInvocationHandler{

    private Person person;

    public Object getInstance(Person person){
        this.person = person;
        Class<? extends Person> aClass = person.getClass();
        return CunstomProxy.newInstance(new CustomClassLoader(),aClass.getInterfaces(),this);
    }



    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("我是淘宝:得给你推荐个宝贝才行");
        System.out.println("开始进行海选...");
        System.out.println("------------");
        method.invoke(this.person, args);
        System.out.println("------------");
        System.out.println("如果合适的话,就下单吧");
        return null;
    }
}


public class ProxyTest {
    public static void main(String[] args) {
        Person instance = (Person) new TaoBao().getInstance(new MuMu());
        instance.shopping();
    }
}

静态代理和动态代理的区别

静态代理:在代理之前,所有东西都是已知的 (人工)
动态代理:在代理之前,所有东西都是未知的(自动化,智能化)

JAVA动态代理

  • 一个接口InvocationHandler和一个类Proxy

被代理对象,接口,代理对象
实现方法 public Object invoke(Object proxy, Method method, Object[] args);
Object proxy被代理类的接口
method 被代理类的方法
方法的参数
调用被代理类的方法通过代理类来调用

public interface Subject {
    void rent();
    void hello(String world);
}
public class RealSubject implements Subject{
    @Override
    public void rent() {
        System.out.println("我是rent方法");    
    }
    @Override
    public void hello(String world) {
        System.out.println("我是hello方法"+world);   
    } 
}
public class DynamicProxy implements InvocationHandler{
    private Object subject;
    public DynamicProxy(Object subject) {
        this.subject = subject;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println(subject.getClass().getName());
        System.out.println("我正在执行");
        method.invoke(subject, args);
        System.out.println("我执行完毕");
        return null;
    }  
}
public class Client {   
    public static void main(String[] args) throws Exception {
        RealSubject realSubject = new RealSubject();
        InvocationHandler dynamicProxy = new DynamicProxy(realSubject);
        Subject newProxyInstance = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(),
                realSubject.getClass().getInterfaces(), dynamicProxy);
        newProxyInstance.rent();
        newProxyInstance.hello("大家好");
    }
}
  • 接口可以代理自己

不用实现类就实现方法

public interface Subject {
    void rent();
    void hello(String world);
}
public class Real implements InvocationHandler{
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //在这里对方法进行拦截,和处理
        //调用方法
        //处理结果或者进行其它操作
        System.out.println("haha");
        return null;
    }
    
}
public class Client {
    public static void main(String[] args) {
        Real real = new Real();
        Subject object = (Subject) Proxy.newProxyInstance(Subject.class.getClassLoader(), new Class<?>[]{Subject.class}, real);
        object.rent();
    }
}
  • 缺陷

接口,被代理者的方法必须添加至接口

Cglib 实现无接口的类的动态代理

  • 入口

代理类实现MethodInterceptor
Enhancer类的setSuperclass(被代理者)
setCallback(代理类)
返回enhancer.create();
调用invoke方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值