代理模式概述
代理模式(Proxy Pattern) ,给某一个对象提供一个代理,并由代理对象控制对原对象的引用,对象结构型模式。
讲人话:在系统内原来代码不懂得情况下,就是现在想找个人帮忙干活,并且在干活的前后还需要处理一些别的业务逻辑,完成对应的目标
1、静态代理
代码
// 被代理父类【今后得代码一定要思考是否要使用父类】
package com.xusj.future.structural.proxy.statics;
/**
* @author xusj
* <br>CreateDate 2022/7/28 22:57
*/
public interface ManTikTok {
void tikTok();
}
// 被代理
package com.xusj.future.structural.proxy.statics;
/**
* @author xusj
* <br>CreateDate 2022/7/28 22:58
*/
public class ZhangTikTok implements ManTikTok {
@Override
public void tikTok() {
System.out.println("我实现了接口");
}
}
// 代理类【聚合被代理类,使用多态,聚合顶层父类,代码扩展性增加】
package com.xusj.future.structural.proxy.statics;
/**
* @author xusj
* <br>CreateDate 2022/7/28 22:59
*/
public class MyProxy implements ManTikTok {
// 被代理对象(多态)
private ManTikTok manTikTok;
// 构造方法(多态)
public MyProxy(ManTikTok manTikTok) {
this.manTikTok = manTikTok;
}
@Override
public void tikTok() {
// 代理之前,我能干事情
System.out.println("我是代理宝强干活的宋喆");
// 代理之后我还能干一些事情
}
}
静态代理:需要现实同一个接口
(1)优点:在不修改目标对象的功能前提下, 能通过代理对象对目标对象进行功能扩展
(2)缺点:因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类;
一旦接口增加方法,目标对象与代理对象都要维护【维护成本高】
动态代理
// 被代理顶层接口1
public interface ManTikTok {
void tiktok();
}
// 被代理顶层接口2
public interface SellTikTok {
void sell();
}
// 被代理实现类
public class LeiTikTok implements ManTikTok,SellTikTok {
@Override
public void tiktok() {
System.out.println("tiktok.... ");
}
@Override
public void sell() {
System.out.println("只要666,赶紧来包...");
}
public void haha(){
System.out.println("hahaha ,......");
}
}
// 代理类
public class JdkTiktokProxy<T> implements InvocationHandler {
private T target;
//接受被代理对象
JdkTiktokProxy(T target){
this.target = target;
}
/**
* 获取被代理对象的 代理对象
* @param t
* @param <T>
* @return
*/
public static<T> T getProxy(T t) {
/**
* ClassLoader loader, 当前被代理对象的类加载器
* Class<?>[] interfaces, 当前被代理对象所实现的所有接口
* InvocationHandler h,
* 当前被代理对象执行目标方法的时候我们使用h可以定义拦截增强方法
*/
Object o = Proxy.newProxyInstance(
t.getClass().getClassLoader(),
t.getClass().getInterfaces(), //必须接口
new JdkTiktokProxy(t));
return (T)o;
}
/**
* 定义目标方法的拦截逻辑;每个方法都会进来的
*
* @param proxy
* @param method
* @param args
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy,
Method method,
Object[] args) throws Throwable {
//反射执行
System.out.println("真正执行被代理对象的方法");
Object invoke = method.invoke(target, args);
System.out.println("返回值:一堆美女");
return invoke;
}
}
Cglib动态代理
1)静态代理和JDK 代理模式都要求目标对象是实现一个接口
,但是有时候目标对象只是一个单独的对象
,并没有实现任何的接口,这个时候可使用目标对象子类来实现代理-这就是 Cglib 代理【通过子类代理】
2)Cglib 代理也叫作子类代理,它是在内存中构建一个子类对象从而实现对目标对象功能扩展, 有些书
也将Cglib代理归属到动态代理。
3)Cglib 是一个强大的高性能的代码生成包,它可以在运行期扩展 java 类与实现 java 接口.它广泛
的被许多 AOP 的框架使用,例如 Spring AOP实现方法拦截就用到了Cglib包
4)在 AOP 编程中如何选择代理模式:【jdk代理和Cglib代理的选择】
目标对象需要实现接口,用 JDK 代理
目标对象不需要实现接口,用 Cglib 代理
5)Cglib 包的底层是通过使用字节码处理框架 ASM 来转换字节码并生成新的类
// 引入spring核心依赖,整合了cglib得功能
<!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.18</version>
</dependency>
// 需要代理得对象(cglib适用只有一个对象)
package com.xusj.future.structural.proxy.cglib;
/**
* @author xusj
* <br>CreateDate 2022/7/28 23:41
*/
public class LeiTikTok {
public void tiktokHaha() {
System.out.println("雷丰阳,tiktok.... haha....");
}
}
// cglib动态代理
package com.xusj.future.structural.proxy.cglib;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* @author xusj
* <br>CreateDate 2022/7/28 23:42
*/
public class CglibProxy {
// 为任意对象创建代理
public static <T> T createProxy(T t) {
// 1、创建增强器
Enhancer enhancer = new Enhancer();
// 2、设置要增强哪个功能。增强器为这个类动态创建一个子类
enhancer.setSuperclass(t.getClass());
// 3、设置回调
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object obj,
Method method, //为了能获取到原方法的一些元数据信息
Object[] args,
MethodProxy proxy) throws Throwable {
//编写拦截的逻辑
System.out.println("cglib上场le .......xxx");
//当前方法的信息
// method.get
// method.getAnnotation()
//目标方法进行执行
Object invoke = proxy.invokeSuper(obj, args);
return invoke;
}
});
Object o = enhancer.create();
return (T) o;
}
}
// 测试类
package com.xusj.future.structural.proxy.cglib;
/**
* @author xusj
* <br>CreateDate 2022/7/28 23:51
*/
public class Test {
public static void main(String[] args) {
//原来的对象都不用new
LeiTikTok tikTok = new LeiTikTok();
LeiTikTok proxy = CglibProxy.createProxy(tikTok);
proxy.tiktokHaha();
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/96217.html