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();
}
}
- 结果