1. 代理模式(Proxy Pattern)
我们需要的东西通过代理对象拿去,而不需要去真正的实现对象,前提是代理对象和被代理对象需要实现相同的接口,而代理在这里相当于中介,并且我们也需要创建一个代理对象
2. 代理的实现
1.2 静态代理
有点类似装饰者模式,话不多说上代码
1.共同的接口
代码语言:javascript复制public interface Dog {
abstract void eat();
}
2.实现类
代码语言:javascript复制public class MyDog implements Dog {
public void eat() {
System.out.println("狗吃肉");
}
}
3.代理类
代码语言:javascript复制public class DogProxy implements Dog {
private Dog dog;
public DogProxy (Dog dog) {
this.dog = dog;
}
public void WashHand(){
System.out.println("吃肉前洗手");
}
public void eat() {
WashHand();
dog.eat();
}
}
4.代理实现
代码语言:javascript复制public static void main(String[] args) {
Dog mydog = new MyDog();
mydog = new WashHandDog(mydog);
mydog.eat();
}
代码语言:javascript复制吃肉前洗手
狗吃肉
1.3 动态代理
动态代理也是基于接口实现的,所以使用上面的接口,该接口增多一个抽象方法用于下面测试
这里重申一下,生成的代理对象是要强转成接口的,接口,接口!!!
代码语言:javascript复制public class MyDog implements Dog {
public void eat() {
System.out.println("狗吃肉");
}
//测试方法
public void jump() {
System.out.println("狗会跳");
}
}
这里需要先了解两个方法
- Proxy类的newInstance() ——生成代理对象
该方法有三个参数,第一个是被代理对象的类加载器,第二个是被代理对象的接口,第三个是处理器也就是下面的InvocationHandler()
- InvocationHandler()——处理器
在代理对象上调用任何方法都会被这个处理器拦截
具体实现
代码语言:javascript复制public static void main(String[] args) {
//被代理对象
Dog mydog = new MyDog();
//生成代理对象,这里InvocationHandler采用匿名函数写法
Dog ProxyDog = (Dog) Proxy.newProxyInstance(mydog.getClass().getClassLoader(), mydog.getClass().getInterfaces(),new InvocationHandler(){
//重写方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//只增强eat方法
if(method.getName().equals("eat")){
System.out.println("吃肉前洗手");
method.invoke(mydog, args);
}else{
method.invoke(mydog, args);
}
return null;
}
});
//代理对象调用增强函数
ProxyDog.eat();
System.out.println("-------测试方法--------");
//没有增强
ProxyDog.jump();
}
代码语言:javascript复制吃肉前洗手
狗吃肉
-------测试方法--------
狗会跳
- Spring的AOP切面编程也是可以用动态代理来实现的,想要了解AOP的 戳这里
回来填坑,之前一直不理解为什么代理对象调用方法就能有方法实现,后面参考了 廖雪峰 的博客豁然开朗 ,这里十分万分感谢
代码语言:javascript复制//动态代理实际上是JDK在运行期动态创建class字节码并加载的过程,它并没有什么黑魔法,把上面的动态代理改写为静态实现类大概长这样
public class HelloDynamicProxy implements Hello {
InvocationHandler handler;
//传入了之前写的处理器
public HelloDynamicProxy(InvocationHandler handler) {
this.handler = handler;
}
//看这里这里没错就是这里!!!,方法中写入invoke,这里就实现调用方法,困惑了我好久
public void morning(String name) {
handler.invoke(
this,
Hello.class.getMethod("morning"),
new Object[] { name });
}
}