• 关于Java代理那些事儿


    代理是啥?就是代替你执行你持有的主要功能,并且能在你的基础之上完成一些其他的功能。代理的目的就是生成一个和原对象具有同样功能的对象。在Java中,代理是一种设计模式。在Spring的面向切面编程(AOP)中,主要就是利用动态代理来实现代码的织入。

    代理分为动态代理和静态代理。顾名思义,动态代理比静态代理扩展性更高,动态代理不用为每一个实现类维护一个代理类。

    静态代理

    为不同的被代理类都维护一个代理类,维护工作量大,不利于扩展。

    建立接口类,即被代理类。

    Worker.java 工人接口类

    public interface Worker {
    
    	public void working();
    
    	public void resting();
    }
    

    SimpleWorker.java 工人实现类

    public class SimpleWorker implements Worker {
    
    	@Override
    	public void working() {
    		System.out.println("I'm working!");
    	}
    
    	@Override
    	public void resting() {
    		System.out.println("I'm resting!");
    	}
    
    }
    

    需求,通过代理调用SimpleWorker的具体的方法,且处理其他逻辑(输出一句话):

    public class WorkerProxy {
    
    	private Worker worker;
    
            // 构造函数传入需要执行的类
    	public WorkerProxy(Worker worker) {
    		this.worker = worker;
    	}
    
            // 代理方法,调用具体实现方法
    	public void working() {
    		System.out.println("excute static proxy.");
    		worker.working();
    	}
    }
    

    运行结果:

    excute static proxy.
    I'm working!
    

    动态代理

    动态代理分为JDK动态代理与CGLIB动态代理。

    JDK动态代理

    JDK动态代理是jre库提供的一种方法,无需额外引入。它是通过类的接口生成代理类。

    生成一个jdk代理,需要实现InvocationHandler接口,重写invoke方法。再用Proxy.newProxyInstance去生成代理类。

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    /**
     * jdk 动态代理
     * @author guilin
     *
     */
    public class JdkProxy implements InvocationHandler{
    
    	private Object target;
    
    	public JdkProxy(Object target) {
    		this.target = target;
    	}
    
    	@Override
    	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    		System.out.println("excute jdk proxy.");
    		Object result = method.invoke(target, args);
    		return result;
    	}
    
    	public Object getInstance() {
    		return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    	}
    }
    

    测试类:

    public class Test {
    	public static void main(String[] args) {
    		// JDK 动态代理
    		SimpleWorker simpleWorker = new SimpleWorker();
    		JdkProxy dynamicProxy = new JdkProxy(simpleWorker);
    		Object proxyObj = dynamicProxy.getInstance();
    		Worker obj = (Worker) proxyObj;
    		obj.working();
            }
    }
    

    运行结果:

    excute jdk proxy.
    I'm working!
    

    CGLIB动态代理

    CGLIB是通过继承父类的公有方法,然后进行重写来实现的。在代码中代理类需要实现MethodInterceptor接口,重写intercept方法。配合Enhancer生成动态代理类。

    import java.lang.reflect.Method;
    
    import org.springframework.cglib.proxy.Enhancer;
    import org.springframework.cglib.proxy.MethodInterceptor;
    import org.springframework.cglib.proxy.MethodProxy;
    
    public class CglibProxy implements MethodInterceptor{
    
    	@Override
    	public Object intercept(Object obj, Method method, Object[] aobj, MethodProxy methodproxy) throws Throwable {
    		System.out.println("excute cglib proxy.");
            // 执行父类方法
    		Object result = methodproxy.invokeSuper(obj, aobj);
    		return result;
    	}
    
    	public Object getInstance(Class<?> superClass) {
            // 获取代理实例
    		Enhancer enhancer = new Enhancer();
    		enhancer.setSuperclass(superClass);
    		enhancer.setCallback(this);
    		return enhancer.create();
    	}
    
    }
    

    测试类:

    public class Test {
    	public static void main(String[] args) {
    		// CGLIB 动态代理
    		CglibProxy cglibProxy = new CglibProxy();
    		Object instance = cglibProxy.getInstance(SimpleWorker.class);
    		Worker obj2 = (Worker) instance;
    		obj2.working();
            }
    }
    

    运行结果:

    excute cglib proxy.
    I'm working!
    

    Spring 默认使用jdk动态代理,而当类没有接口类时,使用CGLIB进行代理。

  • 相关阅读:
    Java之序列化和反序列化
    Java之流的分类
    Java之扫描目录,修改文件内容
    Java之数据流-复制二进制文件
    Java之字符流操作-复制文件
    Java之字节流操作-复制文件
    SQL语句优化原则
    php程序效率优化的一些策略小结
    MYSQL的索引类型:PRIMARY, INDEX,UNIQUE,FULLTEXT,SPAIAL 有什么区别?各适用于什么场合?
    笔记:php有那几种错误提示和查错方法
  • 原文地址:https://www.cnblogs.com/yl-space/p/13620673.html
Copyright © 2020-2023  润新知