尚硅谷设计模式学习(13)---[代理模式(Proxy)---静态代理,动态代理,Cglib代理]
Posted 小智RE0
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了尚硅谷设计模式学习(13)---[代理模式(Proxy)---静态代理,动态代理,Cglib代理]相关的知识,希望对你有一定的参考价值。
🚀🚀🚀尚硅谷传送门==>B站尚硅谷Java设计模式
❤❤❤感谢尚硅谷❤❤❤
🕐🕑🕒最近开始计划学习一下设计模式了,加油!!!
📢代理模式
代理模式:给一个对象提供副本,通过这个 副本对象
来控制 真实对象
的访问。那么就算是想要扩展新的内容或功能,在副本对象上修改即可.
(可理解为分身
,可通过分身
找到本体
,对于分身
的管理操作会影响到本体
,)
被代理的对象可以是远程对象、创建开销大的对象或需要安全控制的对象
具体可分为3种:
静态代理
动态代理 (JDK代理、接口代理)
Cglib代理 (在内存动态的创建对象)
🌈静态代理
代理对象与目标对象要实现相同的接口,然后通过调用相同的方法来调用目标对象的方法。
使用静态代理模式;在不修改目标对象的功能前提下, 能通过代理对象对目标功能扩展;
但是由于代理对象需要与目标对象实现一样的接口,所以就要产生很多代理类;
如果说接口要增加方法,目标对象和代理对象都要增加方法实现.
案例:
代理和目标的共同接口UserDao
//接口 ,目标对象和代理对象都要实现;
public interface UserDao {
//添加用户方法;
public abstract void addUser();
}
目标RealUserDao
//目标;
public class RealUserDao implements UserDao{
@Override
public void addUser() {
System.out.println("目标对象说要添加用户");
}
}
代理ProxyUserDao
//代理;
public class ProxyUserDao implements UserDao{
//把目标聚合过来;
private UserDao target;
public ProxyUserDao(UserDao target) {
this.target = target;
}
@Override
public void addUser() {
System.out.println("静态代理开始-->");
target.addUser();
System.out.println("结束--->");
}
}
模拟客户端Client
public class Client {
public static void main(String[] args) {
ProxyUserDao proxyUserDao =new ProxyUserDao(new RealUserDao());
//通过代理对象,调用到目标对象的方法;
proxyUserDao.addUser();
}
}
/*
静态代理开始-->
目标对象说要添加用户
结束--->
*/
🌈动态代理
只需要目标对象
去实现接口即可 ; 代理对象不需要实现接口.
代理类所在的包:java.lang.reflect.Proxy
代理对象使用JDK的API,动态形式在内存中构建代理对象;
使用方法newProxyInstance( ) 时,
参数 :ClassLoader loader ;指定当前目标对象使用的类加载器;
参数: Class<?>[] interfaces : 目标对象实现的接口.
参数: InvocationHandler h) 执行目标对象方法时,触发事件发生器,会通过反射得到执行的目标对象方法.
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
接口UserDao
//接口 仅需要目标对象实现;
public interface UserDao {
//添加用户方法;
public abstract void addUser();
}
目标类RealUserDao
//目标;
public class RealUserDao implements UserDao{
@Override
public void addUser() {
System.out.println("目标对象说要添加用户");
}
}
代理类
//代理工厂;
public class ProxyFactory {
//维护目标对象;
private Object target;
//初始化;
public ProxyFactory(Object target) {
this.target = target;
}
//动态代理;
public Object getProxyInstance(){
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("动态代理/JDK代理");
Object invoke = method.invoke(target, args);
return invoke;
}
});
}
}
模拟客户端
public class Client {
public static void main(String[] args) {
//创建目标对象;
UserDao realUserDao = new RealUserDao();
//为目标对象 创建 代理对象;
UserDao proxyFactory= (UserDao)new ProxyFactory(realUserDao).getProxyInstance();
proxyFactory.addUser();
}
}
/*
动态代理/JDK代理
目标对象说要添加用户
*/
🌈Cglib代理
Cglib代理
(子类代理
)
在内存中构建一个子类对象 ; 实现对目标对象功能扩展.
Cglib包的底层是通过使用字节码处理框架ASM来转换字节码并生成新的类.
注意代理的类不能定义为final,否则报错java.lang.IllegalArgumentException:
目标对象的方法若为final/static,就不会被拦截(不会执行目标对象额外的业务方法)
需要的maven依赖;
<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.11</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.ow2.asm/asm-commons -->
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm-commons</artifactId>
<version>7.1</version>
</dependency>
类图原理
getInstance ( ) 方法为目标对象target创建代理对象;
重写的 intercept ( ) 方法,实现了对于目标对象的方法调用.
目标类RealUserDao
//目标类;
public class RealUserDao {
//添加用户;
public void addUser(){
System.out.println("用了Cglib的方式,无需使用接口");
System.out.println("添加用户的方法");
}
}
代理类ProxyFactory
//代理;
public class ProxyFactory implements MethodInterceptor {
//定义目标对象;
private Object target;
//初始化;
public ProxyFactory(Object target) {
this.target = target;
}
//返回 target的代理对象;
public Object getProxyInstance(){
//创建工具类;
Enhancer enhancer = new Enhancer();
//设置父类;
enhancer.setSuperclass(target.getClass());
//设置回调函数;
enhancer.setCallback(this);
//返回代理对象;
return enhancer.create();
}
//重写的 intercept () 方法,实现了对于目标对象的方法调用.
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("开始Cglib代理模式");
Object invoke = method.invoke(target, objects);
System.out.println("Cglib代理模式==> 提交 <==");
return invoke;
}
}
模拟客户端
//模拟客户端;
public class Client {
public static void main(String[] args) {
//目标对象;
RealUserDao target =new RealUserDao();
//取到目标对象的 代理对象;
RealUserDao proxyFactory = (RealUserDao) new ProxyFactory(target).getProxyInstance();
//执行代理对象的方法;
proxyFactory.addUser();
}
}
/*
开始Cglib代理模式
用了Cglib的方式,无需使用接口
添加用户的方法
Cglib代理模式==> 提交 <==
*/
以上是关于尚硅谷设计模式学习(13)---[代理模式(Proxy)---静态代理,动态代理,Cglib代理]的主要内容,如果未能解决你的问题,请参考以下文章
尚硅谷设计模式学习(23)---[策略模式(strategy pattern)]