综述:
代理是一种设计模式,一种思想理念,通俗的说,就是一种观念。代理的实现方式有多种:静态代理,动态代理。
静态代理:
静态代理的实现非常简单,在业务类外面再包一层代理类,所有对外的接口都通过代理类进行调用,外部不知道内部业务类的名称等,保证了内部类的安全。本文不做详细说明。
动态代理:
java动态代理实现方式有:Java自带的jdk,javax包下的cglib,以及没用过的javaassist。
jdk实现:
jdk实现是java自带的功能,因为是自带的所以性能应该是最好的。jdk通过反射实现,只能代理目标接口,不能代理实现类。需要继承InvocationHandler接口,使用Proxy实例化。
jdk示例:
* public class FacadeProxy implements InvocationHandler { * Object facade;//可以代理任何类!如果需要代理指定类,在复制的时候个性化赋值! * * public Object createInstance(Object facade){ * this.facade = facade; * //底部调用了构造器的newInstance实例化 * return Proxy.newProxyInstance(facade.getClass().getClassLoader(), facade.getClass().getInterfaces(), this); * * } * * public Object invoke(Object o, Method method, Object[] objects) throws Throwable { * //也就这一步有用,invoke通过实例进行调用 * method.invoke(facade, objects);//可以打日志等 * return null; * } * }
* public static void main(String[] args) { * FacadeProxy fp = new FacadeProxy(); * //对象实例来自反射,而不是new。 * //由于想要实现代理所有类的效果,这里new实例是具体的; * //如果要实现对外安全的效果,里面为空就行,new在代理类里面去具体写上!已验证! * Facade facade = (Facade) fp.createInstance(new FacadeImpl()); * facade.fun(10); * }
Cglib实现:
cglib处于javax包下,通过asm包加载目标类字节码,通过改变字节码创建子类实现。可以代理类,但是肯定不能类里面private方法。需要继承MethodInterceptor接口,使用Enhancer实例化。
Cglib示例:
* public class FacadeProxyByCglib implements MethodInterceptor { 功能同上!!! * * Object facade; * * public Object createInstance(Object facade){ * this.facade = facade; * return Enhancer.create(facade.getClass(), this); * * } * * @Override * public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { * method.invoke(facade, objects); * return null; * } * }
反射:
在运行过程中可以获得一个类的方法与属性,并可以调用一个实例的方法与属性。通用方式为:
1、Class<?> clazz = Class.forName(""); 类.class;实例.getClass();
2、由clazz可以获得方法、属性等。通用方法如getMethod可以获得包括父类在内的public方法,如果要获得private等所有的方法只能用getDeclaredMethod等用decalared修饰的方法,不能获得父类的。
3、如果要操作2获得的方法,需要在实例里面,clazz.newInstance();;在jdk9之后这个方法被注解,大概是建议使用构造器的实现方式:constructor.newInstance();
4、方法、属性需要setAccessible(true):如果是打算操作private方法、属性等,需要设置这个可访问。
5、正常调用method.invoke(实例,参数);