首页 > 其他分享 >动态代理

动态代理

时间:2023-02-08 23:34:54浏览次数:32  
标签:return void Object 代理 private 动态 public

动态代理方法:

import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
* 测试动态代理
* @author Administrator
*/
public class DynamicProxy implements InvocationHandler {

/**
* 动态代理对象
*/
private Object target;
private List<String> needReturnProxy = new ArrayList<>();

public DynamicProxy() {
}

/**
* 构造器注入代理对象
* @param target 动态代理对象
*/
public DynamicProxy(Object target) {
this.target = target;
}

/**
* 获取代理接口对象
* @return 返回代理接口对象
*/
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this);
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
printBeforeMsg();
execBeforeMethod();
Object obj = method.invoke(target, args);
printAfterMsg();
execAfterMethod();
if(CollectionUtils.contains(needReturnProxy.listIterator(), method.getName())){
return proxy;
}
return obj;
}

/**
* 前置打印消息集合
*/
private String[] beforeMsg;

/**
* 设置前置消息
* @param beforeMsg 前置消息
*/
public void setBeforeMsg(String[] beforeMsg) {
this.beforeMsg = beforeMsg;
}

/**
* 前置打印消息方法
*/
private void printBeforeMsg(){
if (beforeMsg==null) {
return;
}
for (String msg : beforeMsg) {
if(StringUtils.isEmpty(msg)){
return;
}
System.out.println(msg);
}
}

/**
* 前置执行方法集合
*/
private Set<List<Object>> beforeMethod;

/**
* 设置前置执行方法
* @param beforeMethod 前置执行方法
*/
public void setBeforeMethod(Set<List<Object>> beforeMethod) {
this.beforeMethod = beforeMethod;
}

/**
* 执行前置方法
*/
private void execBeforeMethod(){
if(beforeMethod==null || beforeMethod.isEmpty()){
return;
}
for (List<Object> list : beforeMethod) {
try{
Method method = (Method)list.get(0);
Object obj = list.get(1);
Object[] args = (Object[])list.get(2);
method.invoke(obj, args);
} catch (Exception e){
System.out.println("beforeSet报错");
e.printStackTrace();
}
}
}

/**
* 后置打印消息集合
*/
private String[] afterMsg;

/**
* 设置后置消息
* @param afterMsg 后置消息
*/
public void setAfterMsg(String[] afterMsg) {
this.afterMsg = afterMsg;
}

/**
* 后置打印消息方法
*/
private void printAfterMsg(){
if (afterMsg==null) {
return;
}
for (String msg : afterMsg) {
if(StringUtils.isEmpty(msg)){
return;
}
System.out.println(msg);
}
}

/**
* 后置执行方法集合
*/
private Set<List<Object>> afterMethod;

/**
* 设置后置执行方法
* @param afterMethod 后置执行方法
*/
public void setAfterMethod(Set<List<Object>> afterMethod) {
this.afterMethod = afterMethod;
}

/**
* 执行后置方法
*/
private void execAfterMethod(){
if(afterMethod==null || afterMethod.isEmpty()){
return;
}
for (List<Object> list : afterMethod) {
try{
Method method = (Method)list.get(0);
Object obj = list.get(1);
Object[] args = (Object[])list.get(2);
method.invoke(obj, args);
} catch (Exception e){
System.out.println("afterSet报错");
e.printStackTrace();
}
}
}

/**
* 设置需要返回代理对象的方法名
* @param needReturnProxy 方法名
*/
public void setNeedReturnProxy(List<String> needReturnProxy) {
this.needReturnProxy = needReturnProxy;
}
}

Person测试接口:
public interface Person {

/**
* 打印名字
*/
void name();

}

两个实现类:
小明实现Person
public class XiaoMing implements Person {

@Override
public void name() {
System.out.println("=====我叫小明=====");
}

}

小红实现Person
public class XiaoHong implements Person{

@Override
public void name() {
System.out.println("=====我叫小红=====");
}

}

测试类:
import java.util.*;

public class TestPerson {

public static void main(String[] args) {
try{
XiaoMing xiaoMing = new XiaoMing();
XiaoHong xiaoHong = new XiaoHong();
DynamicProxy dynamicProxy = new DynamicProxy(xiaoMing);
Person proxy = (Person)dynamicProxy.getProxy();
//设置参数
List<Object> ls = new ArrayList<>();
ls.add(xiaoHong.getClass().getMethod("name"));
ls.add(xiaoHong);
ls.add(null);
Set<List<Object>> set = new HashSet<>();
set.add(ls);
//将小红的name方法在小明的代理方法之前调用
dynamicProxy.setBeforeMethod(set);
//将小红的name方法在小明的代理方法之后调用
dynamicProxy.setAfterMethod(set);
//代理执行name方法
proxy.name();
} catch (Exception e){
e.printStackTrace();
}
}

}
执行结果:

=====我叫小红=====
=====我叫小明=====
=====我叫小红=====

结论:动态代理是通过反射机制去调用被代理的实例对象的方法。代理只能在方法之间切入,不能在方法里切入。

注:小红的类只是顺手写的实现Person接口,并不是一定需要实现这个接口。

标签:return,void,Object,代理,private,动态,public
From: https://www.cnblogs.com/lizhenfeng/p/17103706.html

相关文章

  • golang动态库调用方式
    golang调用动态库在使用第三方功能比较常见。方法如下:编写c语言代码实现动态库的调用,然后cgo引用c代码,间接方式实现动态库的调用。优点:通用性强,没什么难度。缺点:......
  • 静态网站与动态网站的区别 & 静态网站生成工具
    1、静态网站与动态网站静态网站是什么?技术上来讲,静态网站是指网页不是由服务器动态生成的。HTML、CSS和JavaScript文件就静静地躺在服务器的某个路径下,它们的内容与终端......
  • 动态SQL
    一、where+if:<where>自动判断其内部是否有返回值,如果有,则插入一个where并自动删除SQL语句前多余的and或or<selectid="getUserList"resultType="User">select*froms......
  • Vue动态绑定内联样式( v-bind:style )
    <button@click="change"type="button">改变Box大小data(){return{imgStyle:{}}},computed:{imgStyle(){retur......
  • element表单嵌套检验+动态添加
    在写表单的时候,容易碰到这种嵌套表单的数据校验,并且这种表单是动态添加的,网上大部分的做法是表单套表单,实际上只需要一个表单就可以了。为了方便观看,这里只列举了两条数......
  • springboot 动态获取配置信息完成启动
    架构说设计到数据量较大的应用要从k8s中迁出单独机器部署于是将8节点的服务准备迁出,且端口号在数据库中保存在不引入springcloud的方式下启动spring容器中对args进行配......
  • 动态内存new与delete
    动态分配内存new&&delete使用堆区的内存有四个步骤:1)声明一个指针;2)用new运算符向系统申请一块内存,让指针指向这块内存;3)通过对指针解引用的方法,像使用变量一样使用这块内......
  • 关于webpack 开启代理proxy后,接口看不到代理地址的问题。
    今天在项目中发现,  明明在proxy里代理了 接口地址确不是10.10.11.106/front/xxxxxx。这是为啥呢?changeOrigin的修改也是一样,在网络请求中发现host还是没改。这又......
  • Linux配置代理
    临时代理#http代理exporthttp_proxy="http://proxyServer:port/"exporthttp_proxy="socks4://proxyServer:port/"#协议不同#https代理exporthttps_proxy="http......
  • 动态代理-cglib分析
    生成代理类文件的方式jvm添加此启动参数,后面就是代理类class生成的地址-Dcglib.debugLocation=~/baldhead/java/dynamic-proxy-cglib/src/main/java/com/baldhead/dynami......