- 一、定义
- 二、使用场景
- 三、代码样例
- 1.类图
- 2.静态代理
- 3.JDK动态代理
- 4.Cglib动态代理
- 四、优缺点
- 五、拓展延伸
- 1.jdk和cglib动态代理类反编译
- 2.jdk和cglib动态代理区别
- 结尾
一、定义
所谓代理模式是指客户端并不直接调用实际的对象,而是通过调用代理对象,来间接的调用实际的对象。通俗的来讲代理模式就是我们生活中常见的中介。
二、使用场景
-
热门框架源码:Spring AOP、Mybatis Mapper
-
权限管理、异常处理、 *** 作日志、事务控制
三、代码样例 1.类图 2.静态代理
/**
* 公共接口
*/
public interface Singer {
void sing();
}
/**
* 具体角色,男歌手
*/
public class MaleSinger implements Singer{
private String name;
public MaleSinger() {
}
public MaleSinger(String name) {
this.name = name;
}
@Override
public void sing() {
System.out.println(this.name+"男歌手在唱歌");
}
}
/**
* 代理角色
*/
public class Agent implements Singer {
//代理角色要有一个被代理角色
private MaleSinger singer;
public Agent(MaleSinger singer) {
this.singer = singer;
}
@Override
public void sing() {
System.out.println("协商出场费,做会场工作");
//一定是被代理角色歌手去唱歌
singer.sing();
System.out.println("会场收拾,结算费用");
}
}
/**
* 静态代理客户端
*/
public class StaticProxyClient {
public static void main(String[] args) {
MaleSinger singer=new MaleSinger("周杰伦");
Agent agent=new Agent(singer);
//通过代理来运行唱歌
agent.sing();
}
}
3.JDK动态代理
/**
* jdk动态代理类工厂
*/
public class JdkProxyFactory {
/**
* 动态生成代理对象
* @param target
* @return
*/
public static <T> T getProxyBean(T target){
Class clazz = target.getClass();
//在JDK中动态生成代理对象的方法
return (T) Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("协商出场费,做会场工作");
Object obj = method.invoke(target,args);
System.out.println("会场收拾,结算费用");
return obj;
}
});
}
}
/**
* jdk动态代理客户端
*/
public class JdkProxyClient {
public static void main(String[] args) {
//设置用于输出jdk动态代理产生的类
System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
Singer singer = new MaleSinger("周杰伦");
JdkProxyFactory.getProxyBean(singer).sing();
System.out.println("aa");
}
}
4.Cglib动态代理
/**
* cglib动态代理类工厂
*/
public class CglibProxyFactory {
/**
* 动态生成代理对象
* @param target
* @return
*/
public static <T> T getProxyBean(T target){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("协商出场费,做会场工作");
Object obj = method.invoke(target,objects);
System.out.println("会场收拾,结算费用");
return obj;
}
});
return (T) enhancer.create();
}
}
/**
* cglib动态代理客户端
*/
public class CglibProxyClient {
public static void main(String[] args) {
//用于输出生成的代理class文件,"D:/test/designpattern"表示存储在class文件夹中
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,"D:/test/designpattern");
Singer singer = new MaleSinger("周杰伦");
CglibProxyFactory.getProxyBean(singer).sing();
}
}
四、优缺点
优点:
- 1、代理模式在客户端与目标对象之间起到一个中介作用和保护目标对象的作用
- 2、代理对象可以扩展目标对象的功能
- 3、代理模式能将客户端与目标对象分离,在一定程度上降低了系统的耦合度,增加了程序的可扩展性
缺点:
- 1、代理模式会造成系统设计中类的数量增加
- 2、在客户端和目标对象之间增加一个代理对象,会造成请求处理速度变慢
- 3、增加了系统的复杂度
五、拓展延伸 1.jdk和cglib动态代理类反编译
JDK代理类反编译:
Cglib代理类反编译:
Jdk动态代理:
利用拦截器加上反射机制生成一个代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。
特点:
JDK动态代理只能对实现了接口的类生成代理,而不能针对类
Cglib动态代理:
利用ASM框架,对代理对象类生成的class文件加载进来,通过修改其字节码生成子类来处理。
特点:
Cglib是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,并覆盖其中方法的增强,但是因为采用的是继承,所以该类或方法最好不要生成final,对于final类或方法,是无法继承的
结尾
- 感谢大家的耐心阅读,如有建议请私信或评论留言。
- 如有收获,劳烦支持,关注、点赞、评论、收藏均可,博主会经常更新,与大家共同进步
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)