什么是代理?
代理(Proxy)模式是一种结构型设计模式,主要解决的问题是:在直接访问对象时带来的问题。
代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。
代理有什么好处?
1.保护真实对象
2.让真实对象职责更明确
3.扩展
静态代理
package com.xcy.proxy;
/**
* 接口,抽象对象(抽象功能)
* @author xcy
*
*/
public interface Subject {
public void myFunction();
}
package com.xcy.proxy;
/**
* 真实对象,也叫委托类,需要委托该类给代理类
* @author xcy
*
*/
public class SubjectImpl implements Subject{
@Override
public void myFunction() {
System.out.println("我是实现类的接口,执行实现类的核心功能");
}
}
package com.xcy.proxy;
/**
* 代理类,继承了接口,并可以在核心方法前后写代理功能
* @author xcy
*
*/
public class SubjectProxy implements Subject{
private Subject realsubject;
public SubjectProxy(Subject realsubject) {
this.realsubject = realsubject;
}
@Override
public void myFunction() {
System.out.println("执行代理的前置功能");
realsubject.myFunction();
System.out.println("执行代理的后置功能");
}
}
package com.xcy.proxy;
/**
* 客户端中创建代理对象,调用代理方法
* @author xcy
*
*/
public class Client {
public static void main(String[] args) {
Subject function = new SubjectProxy(new SubjectImpl());
function.myFunction();
}
}
静态代理的缺点
代理类委托类实现了相同的接口,如果接口中有大量方法(上面的例子接口只有一个方法),这些方法必须在委托类和代理类中均实现方法,如果是相同的代理功能(方法)需要加入到核心功能(方法)中,那么在代理类中实现每个接口时候均需要写相同的代理功能(方法)代码,令代码出现冗余。
而且,如果换了一个对象(委托类),但是你的代理功能是相同的,那么要实现相同的代理功能,你要再建一个代理类,并且把代理类的方法全部再写一遍。事实上,你的要求只是想在这个接口的全部方法中加入相同代理功能罢了,但静态代理只能让你对接口的每个方法进行单独的重复的添加相同的代理方法,而且委托对象一换,代理类也要是新建再写,即使代理功能相同。因为,静态代理在编译器就已经确定被代理的对象,针对上文静态代理的却邪,我们引入了动态代理。
动态代理
动态代理是在运行时,通过反射机制实现动态代理,并且能够代理各种类型的对象。
jdk动态代理
在Java中要想实现动态代理机制,需要java.lang.reflect.InvocationHandler接口和 java.lang.reflect.Proxy 类的支持。
package com.xcy.proxy;
/**
* 接口,抽象对象(抽象功能)
* @author xcy
*
*/
public interface Subject {
public void myFunction1();
public void myFunction2();
public void myFunction3();
}
package com.xcy.proxy;
/**
* 真实对象,也叫委托类,需要委托该类给代理类
* @author xcy
*
*/
public class SubjectImpl implements Subject{
@Override
public void myFunction1() {
System.out.println("我的方法1");
}
@Override
public void myFunction2() {
System.out.println("我的方法2");
}
@Override
public void myFunction3() {
System.out.println("我的方法3");
}
}
package com.xcy.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* 代理类,继承了InvocationHandler接口,实现invoke方法,并可以在invoke方法前后写代理功能
* @author xcy
*
*/
public class SubjectImplProxy implements InvocationHandler {
private SubjectImpl subject;
public SubjectImplProxy(SubjectImpl subject) {
this.subject = subject;
}
@Override
//关联的这个实现类的方法被调用时将被执行
/*InvocationHandler接口的方法,proxy表示代理,method表示原对象被调用的方法,args表示方法的参数*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("前置代理方法");
Object result = method.invoke(subject, args);
System.out.println("后置代理方法");
return result;
}
}
package com.xcy.proxy;
/**
* 客户端中创建代理对象,调用代理方法
*/
import java.lang.reflect.Proxy;
public class Client {
public static void main(String[] args) {
SubjectImplProxy subjectImplProxy = new SubjectImplProxy(new SubjectImpl());
//第一个参数:反射时使用的类加载器
//第二个参数:Proxy需要实现什么接口
//第三个参数:通过接口对象调用方法时,需要调用哪个类的invoke方法
Subject subject = (Subject) Proxy.newProxyInstance(Client.class.getClassLoader(),new Class[]{Subject.class}, subjectImplProxy);
subject.myFunction1();//根据多态特性,调的是代理类的方法,invoke()方法,其通过反射可以在内部调用委托类的核心方法,并书写代理方法
subject.myFunction2();
subject.myFunction3();
}
}
我们可以看到,通过Proxy.newProxyInstance(loader, interfaces, h)方法获取任意委托类的动态代理对象,只要我们在代理类中实现InvocationHandler接口,重写invoke(subject, args)方法,即可通过动态代理对象调用代理方法。
参考博客链接:https://blog.youkuaiyun.com/hejingyuan6/article/details/36203505