1.java的静态代理
静态代理和动态代理的相同点:都必须实现相同接口
假设我们有一个接口类 Subject,真实实现类(将要被代理的对象)RealSubject ,带来对象类ProxySubject
我们看下静态代理的实现方式:代码如下
接口类 Subject.java
public interface Subject{
String sayHello(String name);
}
接口实现类,需要被代理的对象类 RealSubject.java
public class RealSubject implements Subject{
@Override
public String sayHello(String name){
return "Hello" + name;
}
}
代理对象ProxySubject,也需要实现接口类
public class ProxySubject implements Subject{
Subject subject = new RealSubject();//关键是这一步,代理对象中创建被代理对象来实现代理效果
@Override
public String sayHello(String name){
//执行方法前可以做一些事情
subject.sayHello(name);
//之后也可以做一些事情
}
}
测试代码
public class Main {
public static void main(String[] args) {
Subject proxySubject = new ProxySubject();
proxySubject.sayHello("Cronous");
}
}
静态代理的问题:假设我们需要代理的类中方法特别多的话,代理类就需要重写太多的方法,代理类 就会显得非常的庞大,所以动态代理就产生了
2.java动态代理
我们还是使用上面的例子举例
接口类 Subject.java
public interface Subject{
String sayHello(String name);
}
接口实现类,需要被代理的对象类 RealSubject.java
public class RealSubject implements Subject{
@Override
public String sayHello(String name){
return "Hello" + name;
}
}
这里和静态代理不同,我们需要调用处理器实现类,我们需要写一个类实现InvocationHandler
接口
步骤如下:
1.先写个处理器实现类,该类实现
InvocationHandler
接口
2.重写他的invoke
方法
public class InvocationHandlerImpl implements InvocationHandler{
private Object subject;//被代理对象
public InvocationHandlerImpl(Object subject)
{
this.subject = subject;//构造函数传入被代理对象
}
/**
* @param proxy 代理类实例
* @param method 被调用的方法对象
* @param args 调用参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
//在代理真实对象前我们可以添加一些自己的操作
System.out.println("before invoke");
System.out.println("Method:" + method);
//当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
Object returnValue = method.invoke(subject, args);
//在代理真实对象后我们也可以添加一些自己的操作
System.out.println("after invoke");
return returnValue;
}
}
测试代码
执行步骤
1.先创建一个被代理对象
2.创建处理器实体类并传入被代理对象
3.因为代理对象实例化需要三个参数,类装载器、接口及处理器。所以我们需要获取这三个参数
public class Main {
public static void main(String[] args) {
//代理的真实对象
Subject realSubject = new RealSubject();
//创建处理器实体
InvocationHandler handler = new InvocationHandlerImpl(realSubject);
ClassLoader loader = realSubject.getClass().getClassLoader();
Class[] interfaces = realSubject.getClass().getInterfaces();
/**
* 该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例
*/
Subject subject = (Subject) Proxy.newProxyInstance(loader, interfaces, handler);
System.out.println("动态代理对象的类型:"+subject.getClass().getName());
String hello = subject.sayHello("cronous");
System.out.println(hello);
}
}
控制台打印:
动态代理对象的类型:com.sun.proxy.$Proxy0
before invoke
Method:public abstract java.lang.String gt.Subject.sayHello(java.lang.String)
after invoke
Hellocronous