Java之动态代理

Java中的静态代理和动态代理

代理的解释


  • 代理的概念
    生活中的代理是很常见的,比如代购、律师、中介等,他们都有一个共性就是帮助被代理人处理一些前前后后的事情。而被代理人只需要专注做自己要做的那部分事情就可以了。
    Java中的代理也是类似的,代理模式可以实现帮助被代理者完成一些前期的准备工作和后期的善后工作,但是核心的业务逻辑仍然是由被代理者完成。
  • 代理的优点
    被代理类只需要专注于自己的核心代码即可,剩下的交给代理类就可以了,使得代码更加简洁,分工明确。
  • 代理的构成
    代理模式由一个公共的接口、一个代理角色、一个被代理角色构成。

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


  • 静态代理
    运行之前,代理类就已经存在了,也就是自己创建的

  • 动态代理
    代理类在运行时创建,动态代理,多留了并不是在Java代码中定义的,而是在运行时产生的


动态代理的俩种实现方式

一种是JDK反射机制提供的代理。
一种是CGLIB代理。在JDK代理,必须提供接口,而CGLIB则不需要提供接口,在Mybatis里两种动态代理技术都已经使用了,在Mybatis中通常在延迟加载的时候才会用到CGLIB动态代理。

JDK动态代理

这个目标类必须继承实现类,而不是基类
我们现在有俩个类,一个是返回当前时间的,一个是闹铃响了俩秒后关闭的,我们现在想让闹钟在响之前展示一下时间,在响之后再次展示一下时间

public interface ClockRing {
	void ring();
}
import com.demo.DynamicProxy.CGLIB.ClockRing;

public class Clock implements ClockRing {
	public void ring() {
		System.out.println("闹钟响了.....");
		try {
			Thread.sleep(2000);
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		System.out.println("关闭闹钟.....");
	}
}
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateUtils {
	public static void pasreDate() {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		System.out.println(sdf.format(new Date()));
	}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class ProxyTest implements InvocationHandler {

	// 目标类
	private Object target;
	// 增强类
	private DateUtils dateUtils;

	// 构造函数
	public ProxyTest(Object target, DateUtils dateUtils) {
		super();
		this.target = target;
		this.dateUtils = dateUtils;
	}

	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		// TODO Auto-generated method stub
		dateUtils.pasreDate();
		Object interceptor = method.invoke(this.target, args);
		dateUtils.pasreDate();
		return interceptor;
	}

}
import java.lang.reflect.Proxy;

import com.demo.DynamicProxy.CGLIB.ClockRing;

public class Test {
	public static void main(String[] args) {
		Clock clock = new Clock();
		DateUtils dateUtils = new DateUtils();
		ProxyTest proxyTest = new ProxyTest(clock, dateUtils);
		//目标类
		ClockRing clock2 = (ClockRing)Proxy.newProxyInstance(clock.getClass().getClassLoader(), clock.getClass().getInterfaces(), proxyTest);
		clock2.ring();
	}
}
  • 结果
    在这里插入图片描述

CGLIB动态代理

import java.text.SimpleDateFormat;
import java.util.Date;

public class DateUtils {
	public static void parseDate() {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		System.out.println(sdf.format(new Date()));
	}
}
public class Clock {
	public void ring() {
		System.out.println("闹钟响了.....");
		try {
			Thread.sleep(2000);
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		System.out.println("关闭闹钟.....");
	}
}
import java.lang.reflect.Method;

import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

public class ProxyTest implements MethodInterceptor {

	public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
		// TODO Auto-generated method stub
		DateUtils.parseDate();
		Object intercept = arg3.invokeSuper(arg0, arg2);
		DateUtils.parseDate();
		return intercept;
	}
}
import org.springframework.cglib.proxy.Enhancer;

public class Test {
	public static void main(String[] args) {

		ProxyTest proxyTest = new ProxyTest();
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(Clock.class);
		enhancer.setCallback(proxyTest);

		Clock proxy = (Clock) enhancer.create();
		proxy.ring();

	}
}
  • 结果
    在这里插入图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
动态代理是指在运行时动态地创建代理类的机制。在 Java 中,动态代理可以使用 `java.lang.reflect.Proxy` 类实现。 要实现动态代理,你需要定义一个接口并创建该接口的实现类。然后你可以使用 `Proxy` 类的 `newProxyInstance` 方法来创建该接口的代理。这个方法需要三个参数: 1. 一个类加载器(ClassLoader),它负责加载代理类。 2. 一个接口数组,表示该代理类要实现的接口。 3. 一个 `InvocationHandler` 对象,表示当调用代理类的方法时要执行的操作。 下面是一个简单的示例,展示了如何使用动态代理来实现对方法调用的计时功能: ```java import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; // 定义一个接口 interface Hello { void sayHello(); } // 定义一个实现类 class HelloImpl implements Hello { @Override public void sayHello() { System.out.println("Hello World!"); } } // 定义一个 InvocationHandler class TimeHandler implements InvocationHandler { private Object target; public TimeHandler(Object target) { super(); this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { long start = System.currentTimeMillis(); System.out.println("Start Time: " + start); method.invoke(target, args); long end = System.currentTimeMillis(); System.out.println("End Time: " + end); System.out.println("Spent Time: " + (end - start)); return null; } } public class Main { public static void main(String[] args) { Hello hello = new HelloImpl();

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

飝鱻.

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值