java中的动态代理与责任链模式详解

 更新时间:2023年08月28日 10:20:39   作者:等後那场雪  
这篇文章主要介绍了java中的动态代理与责任链模式详解,动态代理提供了一种灵活且非侵入式的方式,可以对对象的行为进行定制和扩展,它在代码重用、解耦和业务逻辑分离、性能优化以及系统架构中起到了重要的作用,需要的朋友可以参考下

动态代理

动态代理是一种设计模式,它允许在运行时创建代理对象,并将方法调用重定向到不同的实际对象。

它使我们能够在不修改现有代码的情况下增加或改变某个对象的行为。

jdk动态代理

被代理接口: 

package com.mzs.test;
public interface DemoService {
    void speak(String str);
    void jump(String str);
}

被代理类: 

package com.mzs.test;
public class DemoServiceImpl implements DemoService {
    public void speak(String string) {
        System.out.println("hello " + string);
    }
    public void jump(String string) {
        System.out.println("hi " + string);
    }
}

代理类: 

package com.mzs.test;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class TestProxy implements InvocationHandler {
    private Object target;
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        return method.invoke(target, args);
    }
    public Object bind(Object target) {
        this.target = target;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }
}

 测试方法:

package com.mzs.test;
public class TestProxyDemo {
    public static void main(String[] args) {
        TestProxy instance = new TestProxy();
        DemoService proxy = (DemoService) instance.bind(new DemoServiceImpl());
        proxy.speak("tom");
    }
}

cglib动态代理

被代理的类:

package com.mzs.test;
public class DemoServiceImpl {
    public void speak(String string) {
        System.out.println("hello " + string);
    }
    public void jump(String string) {
        System.out.println("hi " + string);
    }
}

代理类: 

package com.mzs.test;
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 TestProxy implements MethodInterceptor {
    /**
     * 代理逻辑方法
     *
     * @param o 代理对象
     * @param method 方法
     * @param objects 方法参数
     * @param methodProxy 代理方法
     * @return 方法返回值
     * @throws Throwable 异常
     */
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        return methodProxy.invokeSuper(o, objects);
    }
    /**
     * 生成代理对象
     *
     * @param cls 被代理的Class对象
     * @return 代理对象
     */
    public Object bind(Class cls) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(cls);
        enhancer.setCallback(this);
        return enhancer.create();
    }
}

测试方法:

package com.mzs.test;
public class TestProxyDemo {
    public static void main(String[] args) {
        TestProxy instance = new TestProxy();
        DemoServiceImpl proxy = (DemoServiceImpl) instance.bind(DemoServiceImpl.class);
        proxy.jump("tom");
        proxy.speak("selina");
    }
}

注:导入的依赖,如下:

<!-- cglib proxy -->
<dependency>
  <groupId>cglib</groupId>
  <artifactId>cglib</artifactId>
  <version>2.2.2</version>
</dependency>
<dependency>
  <groupId>asm</groupId>
  <artifactId>asm</artifactId>
  <version>3.3</version>
</dependency>

两者的特点

  • jdk动态代理,使用反射生成实现接口的代理类,被代理类需要实现接口,效率比jdk动态代理高。
  • cglib动态代理,使用asm字节技术生成代理类,继承被代理类,并覆盖并加强父类的方法。 

责任链模式

package com.mzs.testThread1;
public interface UserService {
	void speak(String str);
}
package com.mzs.testThread1;
public class UserServiceImpl implements UserService {
	@Override
	public void speak(String str) {
		System.out.println(str);
	}
}

 MyInterceptor2、MyInterceptor3都一样: (除了1变成2或者3)

package com.mzs.testThread1;
import java.lang.reflect.Method;
public class MyInterceptor implements Interceptor {
	@Override
	public boolean before(Object proxy, Object target, Method method, Object[] args) {
		System.out.println("反射方法前逻辑1");
		return true;
	}
	@Override
	public void around(Object proxy, Object target, Method method, Object[] args) {
		System.out.println("取代被代理对象的方法");
	}
	@Override
	public void after(Object proxy, Object target, Method method, Object[] args) {
		System.out.println("反射方法后逻辑1");
	}
}
package com.mzs.testThread1;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class InterceptorProxy implements InvocationHandler {
	private Object target;
	private Interceptor interceptor;
	public InterceptorProxy(Object target, Interceptor interceptor) {
		this.target = target;
		this.interceptor = interceptor;
	}
	public static Object bind(Object target, Interceptor interceptor) {
		return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InterceptorProxy(target, interceptor));
	}
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object result = null;
		if (interceptor == null)
			result = method.invoke(target, args);
		if (interceptor.before(proxy, target, method, args)) 
			result = method.invoke(target, args);
		else 
			interceptor.around(proxy, target, method, args);
		interceptor.after(proxy, target, method, args);
		return result;
	}
}

测试方法:

package com.mzs.testThread1;
public class TestDemo {
	public static void main(String[] args) {
		UserService proxy1 = (UserService) InterceptorProxy.bind(new UserServiceImpl(), new MyInterceptor());
		UserService proxy2 = (UserService) InterceptorProxy.bind(proxy1, new MyInterceptor2());
		UserService proxy3 = (UserService) InterceptorProxy.bind(proxy2, new MyInterceptor3());
		proxy3.speak("hello");
	}
}

控制台输出如下: 

反射方法前逻辑3
反射方法前逻辑2
反射方法前逻辑1
hello
反射方法后逻辑1
反射方法后逻辑2
反射方法后逻辑3

到此这篇关于java中的动态代理与责任链模式详解的文章就介绍到这了,更多相关java动态代理与责任链内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java中的LinkedList集合详解

    Java中的LinkedList集合详解

    这篇文章主要介绍了Java中的LinkedList集合详解,  LinkedList 是一个双向链表结构(JDK1.6 之前为循环链表,JDK1.7 取消了循环),在任意位置插入删除都很方便,但是不支持随机取值,每次都只能从一端开始遍历,直到找到查询的对象,然后返回,需要的朋友可以参考下
    2023-09-09
  • 使用JDBC实现数据访问对象层(DAO)代码示例

    使用JDBC实现数据访问对象层(DAO)代码示例

    这篇文章主要介绍了使用JDBC实现数据访问对象层(DAO)代码示例,具有一定参考价值,需要的朋友可以了解下。
    2017-10-10
  • RocketMQ broker文件清理源码解析

    RocketMQ broker文件清理源码解析

    这篇文章主要为大家介绍了RocketMQ broker文件清理源码解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04
  • 通过Java连接SQL Server数据库的超详细操作流程

    通过Java连接SQL Server数据库的超详细操作流程

    java相对于其他语言(例如c,c++等)连接数据库要方便得多,那么如何连接呢?下面这篇文章主要给大家介绍了关于通过Java连接SQL Server数据库的超详细操作流程,需要的朋友可以参考下
    2023-03-03
  • Mybatis-Plus通过配置在控制台打印执行日志的实现

    Mybatis-Plus通过配置在控制台打印执行日志的实现

    本文主要介绍了Mybatis-Plus通过配置在控制台打印执行日志的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-04-04
  • Spring Boot打包部署和环境配置详解

    Spring Boot打包部署和环境配置详解

    这篇文章主要介绍了Spring Boot打包部署和环境配置详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-05-05
  • Java实现一键获取Mysql所有表字段设计和建表语句的工具类

    Java实现一键获取Mysql所有表字段设计和建表语句的工具类

    这篇文章主要为大家详细介绍了如何利用Java编写一个工具类,可以实现一键获取Mysql所有表字段设计和建表语句,感兴趣的小伙伴可以了解一下
    2023-05-05
  • Java抛出异常与自定义异常类应用示例

    Java抛出异常与自定义异常类应用示例

    这篇文章主要介绍了Java抛出异常与自定义异常类,结合实例形式分析了Java针对错误与异常处理的try、catch、throw等语句相关使用技巧,需要的朋友可以参考下
    2019-03-03
  • 详解 maven的pom.xml用<exclusion>解决版本问题

    详解 maven的pom.xml用<exclusion>解决版本问题

    这篇文章主要介绍了详解 maven的pom.xml用<exclusion>解决版本问题的相关资料,希望通过本文能帮助到大家,需要的朋友可以参考下
    2017-09-09
  • Mybatis批量插入数据的两种方式总结与对比

    Mybatis批量插入数据的两种方式总结与对比

    批量插入功能是我们日常工作中比较常见的业务功能之一,下面这篇文章主要给大家介绍了关于Mybatis批量插入数据的两种方式总结与对比的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-01-01

最新评论