静态代理(编译时)实现:
package StaitcProxy;
/**
* Created by N3verL4nd on 2017/3/24.
*/
public interface ArithmeticCalculator {
int add(int x, int y);
int sub(int x, int y);
int mul(int x, int y);
int div(int x, int y);
}
package StaitcProxy;
/**
* Created by N3verL4nd on 2017/3/24.
*/
public class ArithmeticCalculatorImpl implements ArithmeticCalculator {
@Override
public int add(int x, int y) {
int result = x + y;
return result;
}
@Override
public int sub(int x, int y) {
int result = x - y;
return result;
}
@Override
public int mul(int x, int y) {
int result = x * y;
return result;
}
@Override
public int div(int x, int y) {
int result = x / y;
return result;
}
}
package StaitcProxy;
/**
* Created by N3verL4nd on 2017/3/25.
*/
public class StaticProxy implements ArithmeticCalculator {
private ArithmeticCalculator calculator; //被代理的对象
public StaticProxy(ArithmeticCalculator calculator) {
this.calculator = calculator;
}
@Override
public int add(int x, int y) {
System.out.println("The method [add] begins");
int result = calculator.add(x, y);
System.out.println("The method [add] ends");
return result;
}
@Override
public int sub(int x, int y) {
System.out.println("The method [sub] begins");
int result = calculator.sub(x, y);
System.out.println("The method [sub] ends");
return result;
}
@Override
public int mul(int x, int y) {
System.out.println("The method [mul] begins");
int result = calculator.mul(x, y);
System.out.println("The method [mul] ends");
return result;
}
@Override
public int div(int x, int y) {
System.out.println("The method [div] begins");
int result = calculator.div(x, y);
System.out.println("The method [div] ends");
return result;
}
}
package StaitcProxy;
/**
* 为其他对象提供一种代理以控制对这个对象的访问。
* 在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
* 其特征是代理类与委托类有同样的接口
* 我们可以借助代理类增加一些功能,而不需要修改原有代码。而真正的业务逻辑还是由委托类(被代理对象)实现。
* Created by N3verL4nd on 2017/3/25.
*/
public class Main {
public static void main(String[] args) {
ArithmeticCalculator calculator = new ArithmeticCalculatorImpl();
ArithmeticCalculator proxy = new StaticProxy(calculator);
int result = proxy.add(10 ,20);
System.out.println("result = " + result);
}
}
1.使用组合。
2.需要实现相同的接口。
动态代理(运行时,通过反射实现)实现:
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
proxy:被代理的对象
method:要调用的方法
args:方法调用时所需要的参数
即调用proxy对象的method方法,传入参数为args。
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{}
loader:类加载器
interfaces:得到全部的接口
h:得到InvocationHandler接口的子类
public Object invoke(Object obj, Object... args)
throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException
{}
Object result = method.invoke(target, args);
执行target对象中带有参数args的method方法。返回值是Object,也既是该方法的返回值。
package DynamicProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
/**
* Created by N3verL4nd on 2017/3/25.
*/
public class DynamicProxy implements InvocationHandler {
private Object target;
public DynamicProxy(Object target) {
this.target = target;
}
public Object getInstance() {
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this
);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(proxy.getClass().getName());
System.out.println("The method [" + method.getName() + "] begins with " + Arrays.toString(args));
Object result = method.invoke(target, args);
System.out.println("The method [" + method.getName() + "] ends with " + result);
return result;
}
}
package DynamicProxy;
/**
* Created by N3verL4nd on 2017/3/25.
*/
public class Main {
public static void main(String[] args) {
ArithmeticCalculator calculator = new ArithmeticCalculatorImpl();
DynamicProxy dynamicProxy = new DynamicProxy(calculator);
ArithmeticCalculator calculatorProxy = (ArithmeticCalculator) dynamicProxy.getInstance();
calculatorProxy.add(10, 20);
/*calculatorProxy.sub(10, 20);
calculatorProxy.mul(10, 20);
calculatorProxy.div(10, 20);*/
}
}
CGLib实现(借助asm实现):
Cglib是一个优秀的动态代理框架,它的底层使用ASM在内存中动态的生成被代理类的子类,使用CGLIB即使代理类没有实现任何接口也可以实现动态代理功能。CGLIB具有简单易用,它的运行速度要远远快于JDK的Proxy动态代理:
net.sf.cglib.proxy.Enhancer – 主要的增强类
net.sf.cglib.proxy.MethodInterceptor – 主要的方法拦截类,它是Callback接口的子接口,需要用户实现
net.sf.cglib.proxy.MethodProxy – JDK的java.lang.reflect.Method类的代理类,可以方便的实现对源对象方法的调用
如使用:
Object o = methodProxy.invokeSuper(proxy, args);//虽然第一个参数是被代理对象,也不会出现死循环的问题。
net.sf.cglib.proxy.MethodInterceptor接口是最通用的回调(callback)类型,它经常被基于代理的AOP用来实现拦截(intercept)方法的调用。这个接口只定义了一个方法
public Object intercept(Object object, java.lang.reflect.Method method,
Object[] args, MethodProxy proxy) throws Throwable;
第一个参数是代理对像,第二和第三个参数分别是拦截的方法和方法的参数。原来的方法可能通过使用java.lang.reflect.Method对象的一般反射调用,或者使用 net.sf.cglib.proxy.MethodProxy对象调用。net.sf.cglib.proxy.MethodProxy通常被首选使用,因为它更快。
package CGLibProxy;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
import java.util.Arrays;
/**
* Created by N3verL4nd on 2017/3/25.
*/
public class CGLibProxy implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("The method " + method.getName() + " begins with " + Arrays.toString(args));
Object result = methodProxy.invokeSuper(obj, args);
System.out.println("The method ends with " + result);
return result;
}
}
package CGLibProxy;
import net.sf.cglib.proxy.Enhancer;
/**
* Created by N3verL4nd on 2017/3/25.
*/
public class Main {
public static void main(String[] args) {
CGLibProxy cgLibProxy = new CGLibProxy();
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(ArithmeticCalculatorImpl.class);
enhancer.setCallback(cgLibProxy);
ArithmeticCalculator calculator = (ArithmeticCalculator) enhancer.create();
calculator.add(10, 20);
}
}
参考:
http://blog.csdn.net/wangyongxia921/article/details/46124197
http://blog.csdn.net/heyutao007/article/details/49738887
https://my.oschina.net/Thehope/blog/856875?nocache=1490407597955
http://blog.csdn.net/dreamrealised/article/details/12885739 |