1. 静态代理
简言之
代理对象 = 增强代码+ 目标对象(原对象)
/**
* 快递员
*/
public class Courier implements IBuy{
@Override
public void buy() {
System.out.println("买一瓶药");
}
}
public interface IBuy {
void buy();
}
public class SFCourierProxy {
// 接收目标对象,以便调用buy方法
private IBuy courier;
public SFCourierProxy(IBuy courier) {
this.courier = courier;
}
// 对目标对象的buy方法进行功能扩展
public void buy() {
System.out.println("所有的药都来自大药店");
courier.buy();
System.out.println("药买好后,将会第一时间送到您身边");
}
}
public class TestProxy {
public static void main(String[] args) {=
IBuy courier = new Courier();
SFCourierProxy sfCourierProxy = new SFCourierProxy(courier);
sfCourierProxy.buy();
}
}
输出结果
所有的药都来自大药店
买一瓶药
药买好后,将会第一时间送到您身边
1.1 优点
- 不直接操作原对象,隔离性好
- 增加原对象功能,修饰或者新增功能方便
1.2 缺点
- 代理对象通常与原对象是1对1关系(当然也可以是1对多),如果需要被代理
- 的对象多,会导致代理类激增,带来冗余与增加维护成本。
- 被代理类发生改变时,代理类也需要改变
2. 动态代理
类的加载指的是将类的.class
文件中的二进制数据读入到内存
中,将其放在Jvm的方法区
内,然后在堆
区创建一个java.lang.Class
对象,用来封装类在方法区内的数据结构。类的加载的最终产品是位于堆区中的Class对象
,Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口。
类对象的创建过程
image.png image.png
Java 中的所有类型包括基本类型(int
, long
, float
等等),即使是数组都有与之关联的 Class 类的对象。
Class对象是由Jvm自动生成的,每当一个类被载入时,Jvm就自动为其生成一个Class对象
作者:dsying
链接:https://juejin.im/post/5dac4edff265da5b5f7588d1
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
两个核心类:Proxy 与 InvocationHandler
public interface UserService {
public void select();
public void update();
}
public class UserServiceImpl implements UserService {
@Override
public void select() {
System.out.println("查询 selectById");
}
@Override
public void update() {
System.out.println("更新 update");
}
}
public class LogDynamicProxy implements InvocationHandler {
Object target; // 被代理的对象,实际的方法执行者
public LogDynamicProxy(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object object = method.invoke(target, args);
end();
return object;
}
private void before() {
System.out.println(String.format("log start time [%s]",new Date()));
}
private void end() {
System.out.println(String.format("log end time [%s]",new Date()));
}
}
public class LogDynamicProxy2 implements InvocationHandler {
....
public <T> T getProxy() {
return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
}
public class DynamicProxyTest {
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
LogDynamicProxy logHandler = new LogDynamicProxy(userService);
UserService userService1 = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(),
userService.getClass().getInterfaces(),logHandler);
userService1.select();
userService1.update();
LogDynamicProxy2 logHandler2 = new LogDynamicProxy2(userService);
UserService userService2 = logHandler2.getProxy();
userService2.select();
userService2.update();
}
}
public class DynamicProxyTest {
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
LogDynamicProxy logHandler = new LogDynamicProxy(userService);
UserService userService1 = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(),
userService.getClass().getInterfaces(),logHandler);
System.out.println("--代理1形式---");
userService1.select();
userService1.update();
System.out.println("--代理2形式---");
LogDynamicProxy2 logHandler2 = new LogDynamicProxy2(userService);
UserService userService2 = logHandler2.getProxy();
userService2.select();
userService2.update();
}
}
--代理1形式---
log start time [Fri Dec 27 11:23:47 CST 2019]
查询 selectById
log end time [Fri Dec 27 11:23:47 CST 2019]
log start time [Fri Dec 27 11:23:47 CST 2019]
更新 update
log end time [Fri Dec 27 11:23:47 CST 2019]
--代理2形式---
log start time [Fri Dec 27 11:23:47 CST 2019]
查询 selectById
log end time [Fri Dec 27 11:23:47 CST 2019]
log start time [Fri Dec 27 11:23:47 CST 2019]
更新 update
log end time [Fri Dec 27 11:23:47 CST 2019]
除了 Proxy.newProxyInstance(userService.getClass().getClassLoader(),
userService.getClass().getInterfaces(),logHandler);
还有另一种创建方法 constructor.newInstance(new InvocationHandler()
public class ProxyTest2 {
public static void main(String[] args) throws Exception{
UserService userService = new UserServiceImpl();
UserService userService1 = (UserService) getProxy(userService);
userService1.select();
userService1.update();
}
private static Object getProxy(Object object) throws Exception {
Class calculatorProxyClazz = Proxy.getProxyClass(UserService.class.getClassLoader(), UserService.class);
Constructor constructor = calculatorProxyClazz.getConstructor(InvocationHandler.class);
UserService proxy = (UserService) constructor.newInstance(new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("开始执行方法");
UserService userService1 = new UserServiceImpl();
Object result = method.invoke(userService1, args);
System.out.println("方法名" + method) ;
System.out.println("执行方法结束");
return result;
}
});
return proxy;
}
}
2.1 优点
- 动态生成代理对象,解决代理类泛滥问题
- 被代理类发生改变时,被代理类不需要改变
2.2 缺点
无论静态代理还是动态代理,都需要一个接口。
如果要包装的防范,没有实现接口怎么办呢?
3.CGLib 动态代理
CGLib 是一个类库,它可以在运行期间动态的生成字节码,动态生成代理类。
网友评论