代理设计模式
代理设计模式分为:
- 静态代理设计模式
- 动态代理设计模式
代理的核心功能是方法增强
一、静态代理
静态代理角色分析:
- 抽象角色:使用接口或者抽象类实现
- 真实角色:被代理的角色
- 代理角色:代理正式角色,代理真实角色后可以做一些附属的操作
- 客户:使用代理角色进行操作
写一个接口
package com.assin;
/**
* @Author:ASSIN
* @Date: 2021/8/31 23:22
*/
public interface Singer {
/**
* 唱歌
*/
void sing();
}
定义男歌手
package com.assin;
/**
* @Author:ASSIN
* @Date: 2021/8/31 23:23
*/
public class MaleSinger implements Singer{
@Override
public void sing() {
System.out.println("男歌手唱歌");
}
}
定义经纪人
package com.assin;
/**
* @Author:ASSIN
* @Date: 2021/8/31 23:22
*/
public class Agent implements Singer{
private Singer singer;
public Agent(Singer singer) {
this.singer = singer;
}
@Override
public void sing() {
System.out.println("协商费用");
singer.sing();
System.out.println("结算费用");
}
}
Client . java 即客户
package com.assin;
/**
* @Author:ASSIN
* @Date: 2021/8/31 23:24
*/
public class Client {
public static void main(String[] args) {
Singer singer = new MaleSinger();
Agent agent = new Agent(singer);
agent.sing();
}
}
客户可以直接接触的是agent,agent在singer演出时完成除开唱歌的其它工作。
还可以使用继承类的方式
优点
- 没有必要为了一下前置后置工作改变singer这个类
- 公共的统一问题交给代理处理
- 公共业务进行扩展或变更时,可以更加方便
这不就是更加符合开闭原则,单一原则吗?
缺点 :
- 每个类都写个代理,麻烦死了。
二、动态代理
- 动态代理的角色和静态代理的一样
- 动态代理使用代码动态自动生成代理代码,静态代理则是我们自己手动写出代理代码
- 动态代理分为两类 : 一类是基于接口动态代理 , 一类是基于类的动态代理
- 基于接口的动态代理----JDK动态代理
- 基于类的动态代理–cglib
动态代理就是当有大量的类需要执行一些共同代码时,我们自己写太麻烦,那能不能直接使用java代码,自动生成一个类帮助我们批量的增强某些方法
1、JDK原生的动态代理
JDK****的动态代理需要了解两个类
核心 : InvocationHandler 和 Proxy , 打开JDK帮助文档看看
【InvocationHandler:调用处理程序】
Object invoke(Object proxy, 方法 method, Object[] args);
//参数
//proxy - 调用该方法的代理实例
//method -所述方法对应于调用代理实例上的接口方法的实例。方法对象的声明类将是该方法声明的接 口,它可以是代理类继承该方法的代理接口的超级接口。
//args -包含的方法调用传递代理实例的参数值的对象的阵列,或null如果接口方法没有参数。原始类 型的参数包含在适当的原始包装器类的实例中,例如java.lang.Integer或java.lang.Boolean 。
【Proxy : 代理】
Proxy.newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
Agent 代理人
package com.assin;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* @Author:ASSIN
* @Date: 2021/8/31 23:22
*/
public class Agent implements InvocationHandler {
private Object object;
public Agent(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("开启");
Object invoke = method.invoke(object,args);
System.out.println("提交");
return invoke;
}
}
Client 客户
package com.assin;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @Author:ASSIN
* @Date: 2021/8/31 23:24
*/
public class Client {
public static void main(String[] args) {
Singer maleSinger = new MaleSinger();
Singer singer = (Singer)Proxy.newProxyInstance(Client.class.getClassLoader(),
new Class[]{Singer.class}, new Agent(maleSinger));
// Agent agent = new Agent(singer);
singer.sing();
}
}
核心:一个动态代理 , 一般代理某一类业务 , 一个动态代理可以代理多个类,代理的是接口!、
2、基于cglib
<dependencies>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<target>14</target>
<source>14</source>
<encoding>utf-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
package com.assin;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @Author:ASSIN
* @Date: 2021/8/31 23:24
*/
public class Client2 {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(MaleSinger2.class);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("------");
Object invoke = methodProxy.invokeSuper(o, objects);
System.out.println("++++++");
return invoke;
}
});
MaleSinger2 maleSinger2 = (MaleSinger2) enhancer.create();
maleSinger2.sing();
}
}
- Java动态代理只能够对接口进行代理,不能对普通的类进行代理(因为所有生成的代理类的父类为
Proxy,Java类继承机制不允许多重继承);
-
cglib能够代理普通类;
-
Java动态代理使用Java原生的反射API进行操作,在生成类上比较高效;cglib使用ASM框架直接对字节码(.class 二进制文件)进行操作,在类的执行过程中比较高效