动态代理技术就是产生一个对象的代理对象,主要用于拦截对真实业务对象的访问。
代理对象的两个概念:
- 代理对象的价值主要是拦截对真实业务对象的访问
- 代理对象应该具有和目标对象(真实业务对象)相同的方法
动态代理对象生成:
"java.lang.reflect.Proxy"类介绍
通过"Proxy"类提供的一个newProxyInstance方法用来创建一个对象的代理对象。newProxyInstance方法用来返回一个代理对象,这个方法总共有3个参数,ClassLoader loader用来指明生成代理对象使用哪个类装载器,Class<?>[] interfaces用来指明生成哪个对象的代理对象,通过接口指定,InvocationHandler h用来指明产生的这个代理对象要做什么事情。所以我们只需要调用newProxyInstance方法就可以得到某一个对象的代理对象了。- 编写生成代理对象的类。 1)定义对象的行为接口(即接口中的方法为对象所属类中方法) 2) 定义实现接口的目标对象类(真实业务对象类) 3) 定义代理对象的类,代理对象中定义一个成员变量(=目标对象),定义一个方法(返回目标对象的代理对象)
public Person getProxy() { //LiuDeHuaProxy是代理对象的类,ldh是目标对象 return (Person) Proxy.newProxyInstance(LiuDeHuaProxy.class.getClassLoader(), ldh.getClass().getInterfaces(), new InvocationHandler() { /** * InvocationHandler接口只定义了一个invoke方法,因此对于这样的接口,我们不用单独去定义一个类来实现该接口, * 而是直接使用一个匿名内部类来实现该接口,new InvocationHandler() {}就是针对InvocationHandler接口的匿名实现类 */ /** * 在invoke方法编码指定返回的代理对象干的工作 * proxy : 把代理对象自己传递进来 * method:把代理对象当前调用的方法传递进来 * args:把方法参数传递进来 * * 当调用代理对象的person.sing("冰雨");或者 person.dance("江南style");方法时, * 实际上执行的都是invoke方法里面的代码, * 因此我们可以在invoke方法中使用method.getName()就可以知道当前调用的是代理对象的哪个方法 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //如果调用的是代理对象的sing方法 if (method.getName().equals("sing")) { System.out.println("我是他的经纪人,要找他唱歌得先给十万块钱!!"); //已经给钱了,经纪人自己不会唱歌,就只能找刘德华去唱歌! return method.invoke(ldh, args); //代理对象调用真实目标对象的sing方法去处理用户请求 } //如果调用的是代理对象的dance方法 if (method.getName().equals("dance")) { System.out.println("我是他的经纪人,要找他跳舞得先给二十万块钱!!"); //已经给钱了,经纪人自己不会唱歌,就只能找刘德华去跳舞! return method.invoke(ldh, args);//代理对象调用真实目标对象的dance方法去处理用户请求 } return null; } }); }
- 动态代理技术应用在过滤器中使用动态代理解决中文乱码。