在传统的面向对象思想中,若是想要实现功能复用,要么继承,要么引用,不管哪一种方式,对代码都有必定的侵入性,耦合无可避免java
若是你想用它加强你程序的功能,你必须改动你的程序代码,那它就具备侵入性! 若是只有一两点须要加强还好说,但若是大量功能点须要被加强,那么工做量就会很大,代码也不优雅! 想象一下,若是你对外公开了一系列接口,忽然领导说了,接口要加权限控制。在哪加? 最笨的固然是写个程序验证逻辑,而后每一个接口都拿来调用一遍。 这也是面向对象的思想短板,在要为程序新增一些通用功能时,只能经过耦合的方式才能进行。 而代理(动态代理)就能很好的解决该问题!git
public interface Subject {
void sayGoodBye();
void sayHello(String str);
boolean isProxy();
}
复制代码
public class RealSubject implements Subject {
@Override
public void sayGoodBye() {
System.out.println("RealSubject 我是原封不动的代码 sayGoodBye ");
}
@Override
public void sayHello(String str) {
System.out.println("RealSubject 我是原封不动的代码 sayHello " + str);
}
@Override
public boolean isProxy() {
System.out.println("RealSubject 我是原封不动的代码 isProxy ");
return false;
}
}
复制代码
public class ProxySubject implements Subject {
private Subject subject;
public ProxySubject(Subject subject) {
this.subject = subject;
}
@Override
public void sayGoodBye() {
//代理类,功能的加强 调用前 sayGoodBye 可作操做(好比是否能调用的权限认证)
System.out.println("ProxySubject sayGoodBye begin " +
"代理类,功能的加强 调用前 sayGoodBye 可作操做(好比是否能调用的权限认证)");
//在代理类的方法中 间接访问被代理对象的方法
subject.sayGoodBye();
System.out.println("ProxySubject sayGoodBye end " +
"这里可处理原方法调用后的逻辑处理");
}
@Override
public void sayHello(String str) {
//代理类,功能的加强 调用前 sayHello 可作操做(好比是否能调用的权限认证) 并测试带参数的方法
System.out.println("ProxySubject sayHello begin " +
"代理类,功能的加强 调用前 sayHello 可作操做(好比是否能调用的权限认证)");
//在代理类的方法中 间接访问被代理对象的方法
subject.sayHello(str);
System.out.println("ProxySubject sayHello end " +
"这里可处理原方法调用后的逻辑处理");
}
@Override
public boolean isProxy() {
//代理类,功能的加强 调用前 isProxy 可作操做(好比是否能调用的权限认证) 并测试带返回的方法
System.out.println("ProxySubject isProxy begin " +
"代理类,功能的加强 调用前 isProxy 可作操做(好比是否能调用的权限认证)");
boolean boolReturn = subject.isProxy();
System.out.println("ProxySubject isProxy end " +
"这里可处理原方法调用后的逻辑处理");
return boolReturn;
}
}
复制代码
public class ProxyMain {
public static void main(String[] args) {
//被代理的对象,某些状况下 咱们不但愿修改已有的代码,咱们采用代理来间接访问
RealSubject realSubject = new RealSubject();
//代理类对象,将原有代码不想修改的对象传入代理类对象
ProxySubject proxySubject = new ProxySubject(realSubject);
//调用代理类对象的方法
proxySubject.sayGoodBye();
System.out.println("******");
proxySubject.sayHello("Test");
System.out.println("******");
proxySubject.isProxy();
}
}
复制代码
ProxySubject sayGoodBye begin 代理类,功能的加强 调用前 sayGoodBye 可作操做(好比是否能调用的权限认证)
RealSubject 我是原封不动的代码 sayGoodBye
ProxySubject sayGoodBye end 这里可处理原方法调用后的逻辑处理
******
ProxySubject sayHello begin 代理类,功能的加强 调用前 sayHello 可作操做(好比是否能调用的权限认证)
RealSubject 我是原封不动的代码 sayHello Test
ProxySubject sayHello end 这里可处理原方法调用后的逻辑处理
******
ProxySubject isProxy begin 代理类,功能的加强 调用前 isProxy 可作操做(好比是否能调用的权限认证)
RealSubject 我是原封不动的代码 isProxy
ProxySubject isProxy end 这里可处理原方法调用后的逻辑处理
复制代码
静态代理(传统代理模)的实现方式比较暴力直接,须要将全部被代理类的全部方法都写一遍,而且一个个的手动转发过去,麻烦并繁琐。因此咱们要学习并使用动态代理。github
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}
复制代码
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException {....}
复制代码
public interface Subject {
void sayGoodBye();
void sayHello(String str);
boolean isProxy();
}
复制代码
public class RealSubject implements Subject {
@Override
public void sayGoodBye() {
System.out.println("RealSubject 我是原封不动的代码 sayGoodBye ");
}
@Override
public void sayHello(String str) {
System.out.println("RealSubject 我是原封不动的代码 sayHello " + str);
}
@Override
public boolean isProxy() {
System.out.println("RealSubject 我是原封不动的代码 isProxy ");
return false;
}
}
复制代码
public class SubjectInvocationHandler implements InvocationHandler {
//这个就是咱们要代理的真实对象
private Object subject;
//构造方法,给咱们要代理的真实对象赋初值
public SubjectInvocationHandler(Object subject) {
this.subject = subject;
}
@Override
public Object invoke(Object object, Method method, Object[] args) throws Throwable {
//在代理真实对象前咱们能够添加一些本身的操做
System.out.println("before Method invoke 代理类,功能的加强 调用前 "+method+" 可作操做(好比是否能调用的权限认证)");
System.out.println("Method:" + method);
//当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用,获得对应的返回值,最后将对应返回值返回
Object obj = method.invoke(subject, args);
//在代理真实对象后咱们也能够添加一些本身的操做
System.out.println("after Method invoke 这里可处理原方法调用后的逻辑处理 ");
return obj;
}
}
复制代码
public class ProxyMain {
public static void main(String[] args) {
//被代理类
Subject realSubject = new RealSubject();
//咱们要代理哪一个类,就将该对象传进去,最后是经过该被代理对象来调用其方法的
SubjectInvocationHandler handler = new SubjectInvocationHandler(realSubject);
//生成代理类
Subject subject = (Subject) Proxy.newProxyInstance(handler.getClass().getClassLoader(),
realSubject.getClass().getInterfaces(), handler);
//输出代理类对象
System.out.println("Proxy : " + subject.getClass().getName());
System.out.println("Proxy super : " + subject.getClass().getSuperclass().getName());
System.out.println("Proxy interfaces : " + subject.getClass().getInterfaces()[0].getName());
//调用代理类sayGoodBye方法
subject.sayGoodBye();
System.out.println("--------");
//调用代理类sayHello方法
subject.sayHello("Test");
System.out.println("--------");
System.out.println("---subject.isProxy()-----" + subject.isProxy());
}
}
复制代码
Proxy : com.sun.proxy.$Proxy0
Proxy super : java.lang.reflect.Proxy
Proxy interfaces : staticproxy.Subject
before Method invoke 代理类,功能的加强 调用前 public abstract void staticproxy.Subject.sayGoodBye() 可作操做(好比是否能调用的权限认证)
Method:public abstract void staticproxy.Subject.sayGoodBye()
RealSubject 我是原封不动的代码 sayGoodBye
after Method invoke 这里可处理原方法调用后的逻辑处理
--------
before Method invoke 代理类,功能的加强 调用前 public abstract void staticproxy.Subject.sayHello(java.lang.String) 可作操做(好比是否能调用的权限认证)
Method:public abstract void staticproxy.Subject.sayHello(java.lang.String)
RealSubject 我是原封不动的代码 sayHello Test
after Method invoke 这里可处理原方法调用后的逻辑处理
--------
before Method invoke 代理类,功能的加强 调用前 public abstract boolean staticproxy.Subject.isProxy() 可作操做(好比是否能调用的权限认证)
Method:public abstract boolean staticproxy.Subject.isProxy()
RealSubject 我是原封不动的代码 isProxy
after Method invoke 这里可处理原方法调用后的逻辑处理
---subject.isProxy()-----false
---subject.isProxy()-----false
复制代码