代理: A代理B对象,则以后 需要访问B对象 ,那就去先访问A对象。
如果想要增强代码,这时看A对象在执行B对象前(后)有木有增加什么逻辑。
1、静态代理
什么是静态代理?代理类由程序员自己写,在编译期就已经确定了。
1)、定义一个 公共的接口
public inferface C{
public void say();
}
2、被代理的对象:
public class B implements C {
@OverLoad
public void say(){
Sysout.system.out("我是B对象");
}
}
3、创建代理对象:
public class A_proxy implement C{
private B target;
//代理对象 需要接收 被代理参数吧,所以这里构造函数这样写
public A_proxy(B object){
this.target=object;
}
@OverLoad
public void say(){
System.out.println("记录日志");//相当于代码增强
target.say(); //调用代理对象的方法
System.out.println("清理数据");//相当于代码增强
}
}
扩展和疑问:
通过上面的测序发现,代理是 代理对象通过调用 被代理对象的方法,无非在调用前后增加一些代码逻辑。这和 子类继承父类的 后 子类重写父类方法, 在重写父类方法内 先写自己的逻辑 再调用父类的该方法,再写自己的逻辑。这两种形式都达到了 对 原有方法的“增强”,那继承算不算代理的一种呢?
2、动态代理
实现动态代理的方式有两种:
1)、JDK 动态代理:
public interface HelloInterface {
void sayHello();
}
2)、被代理对象:
public class Hello implements HelloInterface{
@Override
public void sayHello() {
System.out.println("Hello zhanghao!");
}
}
2、自定义类(该类目的是:是指定运行时将生成的代理类需要完成的具体任务) 实现InvocationHandler 类,因为任何类调用方法 都会经过InvocationHandler 这个类,Invocation:英文含义 调用
public class ProxyHandler implements InvocationHandler{
private Object object;
public ProxyHandler(Object object){
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before invoke " + method.getName());
method.invoke(object, args);
System.out.println("After invoke " + method.getName());
return null;
}
public static void main(String[] args) {
//用于保存生成的字节码文件,查看内容验证,生成的文件路径:classpath:com\sun\proxy下,搜Proxy0就看到了
System.getProperties().setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
//新jdk可能需要使用这个设置 System.getProperties().put("jdk.proxy.ProxyGenerator.saveGeneratedFiles", "true");
HelloInterface hello = new Hello();
//将 被代理对象的父类引用 丢到自定义的处理器中
InvocationHandler handler = new ProxyHandler(hello);
//获取代理对象
HelloInterface proxyHello = (HelloInterface) Proxy.newProxyInstance(hello.getClass().getClassLoader(), hello.getClass().getInterfaces(), handler);
proxyHello.sayHello();
}
输出:
Before invoke sayHello
Hello zhanghao!
After invoke sayHello
}
生成的代理对象的字节码文件为:
内容为:
/*可以看到,动态代理生成的这个类,
首先,继承 被代理的对象(意味着增强代码),且实现 被代理对象的接口(代表实现具体的方法)
其次,该类中,每个方法都去调用super.h.invoke(this, m3, 入参参数);
*/
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package com.sun.proxy;
import com.patpat.cb.api.service.HelloInterface;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class $Proxy0 extends Proxy implements HelloInterface {
private static Method m1;// equal方法
private static Method m3;//sayHellow方法
private static Method m2;//toString方法
private static Method m0;//hashcode方法
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final void sayHello() throws {
try {
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m3 = Class.forName("com.patpat.cb.api.service.HelloInterface").getMethod("sayHello");
m2 = Class.forName("java.lang.Object").getMethod("toString");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
总结: 把我们需要代理的那个类 的 父类引用(接口) 丢到 我们“自定义的处理器”中,自定义的处理器继承了InvocationHandler ,主要是重写它的 invoke()方法。然后通过 Proxy.newPropxyInstance(被代理类的了哦加载器,XX,XX)获取代理对象的引用。
三个传入参数:被代理对象的类加载器、被代理对象的接口、继承了InvocationHandler自定义的处理器实例
对于Proxy.newPropxyInstance(XX,XX,XX)是如何工作的?
运行时解析到了需要加载的类的名称,使用反射技术,通过构造方法获取代理对象。(然后通过字节码技术动态生成对应的class字节码,加载到内存中得到class对象,进一步得到实例对象)。接着就可以调用所属的方法
2、Cglib 动态代理:
3、自己的想法实现的动态代理
3、观察者模式实现
场景:一个对象状态发生改变,监听者发现后就通知其他对象。项目中的应用,数据更新后,需要通知多个系统进行同步更新。
个人理解:虽然也可以不用此模式,但被通知者都是向消息队列中发送消息,就很有用,解耦了嘛,并且异步。
spring的实现:
public class MyEvent extends ApplicationEvent {
private Object datas; //此属性是接收数据的,应改成你发送数据类型的格式
public MyEvent(Object source, Object object) {
super(source);
this.datas = object;
}
//get() set()方法
}
@AllArgsConstructor
@Component
public class MyListener implements ApplicationListener<MyEvent> {
@Override
public void onApplicationEvent(MyEvent event) {
System.out.println("收到事件:" + event);
//tod 通知其他系统的业务逻辑
this.log(event);
this.updateProductPushToMMS(event); //todo
this.updateProductsPushToCms(event);
this.updateProductPriceMqToMMs(event); //todo
}
调用:
class{
@AotuWire
private MyListener myListener;
void ssss(){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
// 注册自定义事件监听器
context.addApplicationListener(myListener); //此处也可以先new MyListener()
// 启动上下文
context.refresh();
// 发布事件,事件源为Context
context.publishEvent(new myEvent(context, eventBO)); // eventBO是封装了我们要携带的数据
// 结束
context.close();
}
}