Java动态代理之实现方法拦截

动态代理
placeholder image
admin 发布于:2019-09-02 22:06:26
阅读:loading

记得在很早的时候(本站另外一篇文章)通过学习视频了解到的Java的动态代理,照着敲出来的示例当时也只是似懂非懂的,直到后面再看视频的时候看到了基于List接口实现的代理,这次是真的懂了许多了,然而长时间抛在脑后时间久了就又需要花费时间去捡起,如果不是下篇文章所实现的示例,可能不会这么快整理出来本篇文章。

本次示例使用动态代理实现方法的前置与后置拦截,与Spring AOP的拦截器一样,可以根据特定类的路径、方法的规则、参数的类型等方式的限定拦截,懒得写了,就当本文是作为个人的笔记分享吧。

代理实现类

package cn.chendd.tips.examples.proxy;

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

/**
 * @author chendd
 * @since 2019-08-31 22:15
 * List
代理示例,简单的List类方法拦截实现
 
*/
public class ObjectProxyHandler implements InvocationHandler {

    
private Object target;
    
private Method method;

    
public ObjectProxyHandler(Object target){
        
this.target = target;
    }

    
@Override
    
public Object invoke(Object object, Method method, Object[] args) throws Throwable {
        
this.method = method;
        Object result = 
null;
        
this.before();
        
try {
            result = method.invoke(
target , args);//方法出错时不执行后置方法
            
this.after();
        } 
catch (Exception e) {
            
this.exception(e);
        }
        
return result;
    }

    
/**
     * 
方法前置
     
*/
    
private void before() {
        System.
out.println("invoke " method.getName() + " before");
    }

    
/**
     * 
方法后置
     
*/
    
private void after(){
        System.
out.println("invoke " method.getName() + " after");
    }

    
/**
     * 
异常处理
     
@param e
     
*/
    
public void exception(Exception e){
        System.
err.println("invoke " method.getName() + " exception");
    }

}

测试类

package cn.chendd.tips.examples.proxy;

import org.junit.Test;

import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;

/**
 * @author chendd
 * @since 2019-08-31 22:27
 * 
测试List代理实现
 
*/
public class ObjectProxyTest {

    
/**
     * List
集合类的方法代理测试
     
*/
    
@Test
    
public void testListProxy(){
        List<String> list = 
new ArrayList<String>();
        ObjectProxyHandler proxyHandler = 
new ObjectProxyHandler(list);
        List<String> listProxy = (List<String>) Proxy.newProxyInstance(getClass().getClassLoader() ,
                list.getClass().getInterfaces() , proxyHandler);
        listProxy.add(
"chendd");
        listProxy.remove(
"chendd");
    }

    
/**
     * 
字符串的比较接口代理
     
*/
    
@Test
    
public void testGeneralProxy(){
        String value = 
"https://www.chendd.cn";
        ObjectProxyHandler proxyHandler = 
new ObjectProxyHandler(value);
        Comparable valueProxy = (Comparable) Proxy.newProxyInstance(getClass().getClassLoader() ,
                value.getClass().getInterfaces() , proxyHandler);
        valueProxy.compareTo(
"chendd");
    }

}

代码说明

(1)ObjectProxyHandler类定义了方法代理实现,并提供before、after、exception三个函数,可通过实现对应的方法去实现对应的逻辑;

(2)ObjectProxyTest测试类中定义了两个test函数,分别是基于List的代理和String代理;

(3)ArrayList是List的代理实现类,对于该集合的代理对象在执行其内置的各个方法都是会被执行前置与后置方法拦截;

(4)当调用的代理类的函数报错时不执行after函数,执行exception函数;

运行示例

image.png

image.png

小总结

(1)动态代理类必须是接口类;

(2)代理实现类只能使用对应接口的实现方法,如上述示例testGeneralProxy函数实现的String代理类,只能使用它的父接口类的compareTo函数;

源码下载

https://gitee.com/88911006/chendd-examples/tree/master/tips/test/main/java/cn/chendd/tips/examples/proxy


 点赞


 发表评论

当前回复:作者

 评论列表


留言区