代理
代理(Proxy)
现在要扩展eat方法的功能,
静态代理(方法的代理)
IPeople接口有eat()方法
public interface IPeople{ void eat(); }
people类实现IPeople
public class People implements IPeople { @Override public void eat() { System.err.println("我吃饭了"); } }
代理people
public class ProxyPeop implements IPeople{ private IPeople target;//target就是要代理的目标对象 public ProxyPeop(IPeople target ) { this.target = target; } @Override public void eat() { //我要洗手 System.out.println("我要洗手"); target.eat(); //我要刷牙 System.out.println("我要刷牙"); } }
测试
@Test public void cc() { IPeople target = new People(); ProxyPeop proxyPeop = new ProxyPeop(target); proxyPeop.eat(); }
不足:有上述代码可知,访问的方法变为代理对象的方法,但真正eat方法还是有目标对象执行。这样就可以不改动原来的代码,,来增加功能。
可以看出,静态代理,依赖于接口,接口变动,,目标对象和代理对象都得改变。且代理类在编译期已经存在,有自己编写。并且如果有增删改查四个
方法在代理类中还是有很多重复代码,,复用性不高。
动态代理(代理的类级别)
代理类不再需要实现目标接口,代理对象由运行时生成,
显而易见,不需要写重复的代码。运行时自动生成代理对象
public class DynamicProxyPeople { private IPeople target; People people = new People();// 目标对象
/*Proxy.newProxyInstance() ClassLoader 类加载器 interface[] 目标对象实现的接口 InvocationHandler InvocationHan实现 * */ public IPeople getProxy() { target = (IPeople)Proxy.newProxyInstance(DynamicProxyPeople.class.getClassLoader(),people.getClass().getInterfaces(),
new InvocationHandler() { /* * proxy 目标对象 * method 目标对象的方法 * args 参数 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.err.println(method.getName());//方法名 System.out.println("我要洗手"); method.invoke(people); System.out.println("我要刷牙"); return null;//f方法返回值 } }); return target; } }
cglib代理
上述两种方式都需接口,但是我们不想写接口呢。cglib就不需要
cglib叫做继承代理,就是生成一个继承了目标对象的代理类(子类)。(可以在运行期间扩展java类和接口)
public class CglibProxy implements MethodInterceptor { private Object target; public CglibProxy(Object target) { this.target = target; } public People getProxy() { Enhancer enhancer = new Enhancer(); //工具类 设置父类 enhancer.setSuperclass(People.class); //设置回调 即 intercept函数 增强代码 enhancer.setCallback(this); //创建子类 Object o = enhancer.create(); return (People) o; } @Override public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { System.out.println("我要洗手"); method.invoke(target,args); System.out.println("我要刷牙"); return null; } }
spring集成了cglib所以需导入spring-core包,生成的代理对象父类为目标对象