简单来说就是你不用去做,别人代替你去处理。
废话不多说直接代码演示。
举个简单的例子:
public interface Hello {
void say(String name);
}
实现类:
public class HelloImpl implements Hello {
public void say(String name) {
System.out.println("hello" + name);
}
}
代理模式:
public class HelloProxy implements Hello {
private Hello hello;
public HelloProxy(){
hello = new HelloImpl();
}
@Override
public void say(String name) {
before();
hello.say(name);
after();
}
private void before(){
System.out.println("Before");
}
private void after(){
System.out.println("After");
}
}
在main方法中测试:
public class Main {
public static void main(String[] args){
Hello helloProxy = new HelloProxy();
helloProxy.say("Mc");
}
}
可以得到:
Before
helloMc
After
这就是所谓的代理模式。
上述代理代码中在main中测试时可以发现,这样的代理,是静态的,需要每次都去写一个XXXProxy类去使用。
为了解决这个问题就衍生出了:
JDK动态代理
public class DynamicProxy implements InvocationHandler {
private Object target;
public DynamicProxy(Object target){
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
target = method.invoke(target,args);
after();
return null;
}
private void before(){
System.out.println("Before");
}
private void after(){
System.out.println("After");
}
}
这是JDK提供的动态代理方案,写一个类继承InvocationHandler.
使用的时候:
public static void main(String[] args){
Hello hello = new HelloImpl();
DynamicProxy dynamicProxy = new DynamicProxy(hello );
Hello helloProxy = (Hello) Proxy.newProxyInstance(
hello.getClass().getClassLoader(),
hello.getClass().getInterfaces(),
dynamicProxy);
helloProxy.say("Mc");
}
意思就是使用DynamicProxy类去包装HelloImpl示例,然后再调用JDK给我们提供的Proxy类的工厂方法去动态创建一个Hello接口的代理类。
避免倒是都是
Proxy.newProxyInstance
可以重构一下:
写出:
public class DynamicProxy implements InvocationHandler {
private Object target;
public DynamicProxy(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
target = method.invoke(target, args);
after();
return null;
}
private void before() {
System.out.println("Before");
}
private void after() {
System.out.println("After");
}
public <T> T getProxy() {
return (T) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this);
}
}
添加一个getProxy方法。
这样使用的时候就简便多了:
public static void main(String[] args){
Hello hello = new HelloImpl();
DynamicProxy dynamicProxy = new DynamicProxy(hello );
Hello helloProxy = dynamicProxy.getProxy();
helloProxy.say("Mc");
}
这样使用的时候直接填写实现类即可使用代理。
CGlib动态代理
DynamicProxy非常不错,接口变了,动态代理类无需改变。而静态代理类则不同,接口变了,实现了要变,动态代理类也需要变。
但是DynamicProxy 也有不好的时候,比如要代理一个没有任何接口的类,他就不可以。
因此我们又发现了CGlib这个类库。
public class CGLibProxy implements MethodInterceptor {
public <T> T getProxy(Class<T> cls){
return (T) Enhancer.create(cls,this);
}
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
before();
o = methodProxy.invokeSuper(o,objects);
after();
return o;
}
private void before() {
System.out.println("Before");
}
private void after() {
System.out.println("After");
}
}
CGLib给我们提供的是方法级别的代理,也可以理解为对方法的拦截(就是方法拦截器吧)。
使用的时候:
public static void main(String[] args){
CGLibProxy cgLibProxy = new CGLibProxy();
Hello helloProxy = cgLibProxy.getProxy(HelloImpl.class);
helloProxy.say("Mc");
}
还可以再优化,将CGLibProxy写成单例模式,不用每次都new一个。
private static CGLibProxy cgLibProxy;
public static synchronized CGLibProxy getCgLibProxy() {
if (cgLibProxy == null) {
synchronized (CGLibProxy.class) {
cgLibProxy = new CGLibProxy();
}
}
return cgLibProxy;
}
这样只需要一行代码就完成测试。
Hello helloProxy = CGLibProxy.getCgLibProxy().getProxy(HelloImpl.class);
helloProxy.say("MC");