简介
看了挺多关于代理方面的文章,这是我个人对代理的一些粗浅的理解。
代理模式是一种毕竟常见的设计模式。
就好比歌手要开展演唱会,背后会有一个经纪人帮忙接活动,时间安排等。
在这里,歌手就是提供服务的对象,而经纪人就是代理。
而代理又分为 静态代理 与 动态代理
静态代理
组成结构:
- 接口类
- 接口对象
- 代理类
/**
* 1.歌手接口
*/
public interface Singer {
// 歌手有唱歌这么个天赋
public void singsong();
}
/**
* 2.歌手的实例化-对象(刘德华)
*/
public class LiuSinger implements Singer{
@Override
public void singsong(){
System.out.println("刘德华-正在激情演唱歌曲XXX");
}
}
package test2;
/**
* 3.静态代理类
* Created by Sheldon on 2019/11/5.
*/
public class SingerStaticProxy implements Singer{
// 歌手这一成员变量
private Singer singer;
public SingerStaticProxy(Singer singer){
this.singer = singer;
}
// 唱歌之前
public void beforeSing(){
System.out.println("布置会场ing");
}
// 唱歌之后
public void afterSing(){
System.out.println("清理会场ing");
}
@Override
public void singsong(){
// 调用之前的操作
beforeSing();
// 调用代理对象的操作
singer.singsong();
// 调用之后的操作
afterSing();
}
// 测试方法
public static void main(String[] args) {
// 创建歌手对象
Singer singer = new LiuSinger();
// 创建代理对象
SingerStaticProxy proxy = new SingerStaticProxy(singer);
// 调用歌手操作
proxy.singsong();
}
}
动态代理
区别
- 静态代理 通常只代理一个类,动态代理是代理一个接口下的多个实现类。
- 静态代理 事先知道要代理的是什么,而动态代理不知道要代理什么东西,只有在运行时才知道。
- 静态代理 由程序员创建代理类或特定工具自动生成源代码再对其编译。
- 动态代理 是实现 JDK 里的 InvocationHandler 接口的 invoke 方法,但注意的是代理的是接口,也就是你的业务类必须要实现接口,通过 Proxy 里的 newProxyInstance 得到代理对象。
AOP 便是通过动态代理实现的
一般通过以下固定的套路实现的。
方法一:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 动态代理
* Created by Sheldon on 2019/11/5.
*/
public class SingerDynamicProxy implements InvocationHandler {
// 代理的对象
private Object object;
public SingerDynamicProxy(Object object){
this.object = object;
}
// 唱歌之前
public void beforeSing(){
System.out.println("动态-布置会场ing");
}
// 唱歌之后
public void afterSing(){
System.out.println("动态-清理会场ing");
}
/**
* 代理对象要执行的方法:{即真正需要执行的代理对象的业务方法}
* @param o 参数1:代理类对象
* @param method 参数2:被代理对象的业务方法 {注意:这里是概论的即统一所有的被代理对象的方法都用method表示,具体的是什么方法就需要具体的传入被代理对象来决定}
* @param arg 参数3:被代理对象的方法的参数
* @return
*/
@Override
public Object invoke(Object o, Method method, Object[] arg) throws Throwable {
// 切面代码
beforeSing();
// 要执行的被代理对象的业务方法
Object obj = method.invoke(object, arg);
// 切面代码
afterSing();
return null;
}
// 测试类
public static void main(String[] args) {
// 创建刘德华歌手
LiuSinger liu = new LiuSinger();
// 创建代理对象
SingerDynamicProxy proxy = new SingerDynamicProxy(liu);
// 绑定歌手跟代理的关系
// getClassLoader()叫类加载器:把一个类加载到内存里面
// getInterfaces() 获取类的所有接口方法
// proxy 传入要绑定的代理对象
Singer singer = (Singer) Proxy.newProxyInstance(
liu.getClass().getClassLoader(),
liu.getClass().getInterfaces(),
proxy);
// 调用歌手方法
singer.singsong();
}
}
方法二:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 动态代理
* Created by Sheldon on 2019/11/5.
*/
public class SingerDynamicProxy implements InvocationHandler {
// 代理的对象
private Object object;
public SingerDynamicProxy(Object object){
this.object = object;
}
// 唱歌之前
public void beforeSing(){
System.out.println("动态-布置会场ing");
}
// 唱歌之后
public void afterSing(){
System.out.println("动态-清理会场ing");
}
// 绑定关系(返回绑定好关系的代理实例)
// getClassLoader()叫类加载器:把一个类加载到内存里面
// getInterfaces() 获取类的所有接口方法
// 如下是固定的写法,套路来的,得到代理对象(与传入对象有关)
public Object newProxyInstance(){
return Proxy.newProxyInstance(
object.getClass().getClassLoader(),
object.getClass().getInterfaces(),
this);
}
/**
* 代理对象要执行的方法:{即真正需要执行的代理对象的业务方法}
* @param o 参数1:代理类对象
* @param method 参数2:被代理对象的业务方法 {注意:这里是概论的即统一所有的被代理对象的方法都用method表示,具体的是什么方法就需要具体的传入被代理对象来决定}
* @param arg 参数3:被代理对象的方法的参数
* @return
*/
@Override
public Object invoke(Object o, Method method, Object[] arg) throws Throwable {
// 切面代码
beforeSing();
// 要执行的被代理对象的业务方法
Object obj = method.invoke(object, arg);
// 切面代码
afterSing();
return null;
}
// 测试类
public static void main(String[] args) {
// 创建刘德华歌手
LiuSinger liu = new LiuSinger();
// 创建代理对象
SingerDynamicProxy proxy = new SingerDynamicProxy(liu);
// 获取代理对象实例
Singer proxyInstance = (Singer) proxy.newProxyInstance();
// 调用歌手方法
proxyInstance.singsong();
}
}