一、什么是代理
代理对象代替被代理对象干活
二、代理作用
对被代理对象方法的增强
三、代理的种类:静态代理、动态代理
3.1、静态代理
3.1.1、定义抽象行为的类[抽象类、接口]
3.1.2、定义具体类实现抽象行为
3.1.3、定义代理类实现和具体类相同接口
3.1.4、代理类中必须持有实现类对应的引用
3.1.5、缺点:只能代理一类对象
3.2、动态代理
3.2.1、动态代理2种:JDK动态代理、cglib代理
3.2.2、JDK动态代理:为实现接口的类动态创建代理类(即:帮你生成代理对象, 只能代理实现接口的类),然后调用回调方法。
四、代码演示
4.1静态代理
package com.statics.proxy; /** * 接口 */ public interface IFunction { public String getBtnName(); void click(); } package com.statics.proxy; /** * 实体对象:按钮 */ public class Button implements IFunction { private String btnName; public String getBtnName(){ return btnName; } public Button(String btnName){ this.btnName = btnName; } @Override public void click() { System.out.println(this.btnName+"按钮被点击了"); } } package com.statics.proxy; /** * 负责鉴权的代理类。即:在调用按钮前,检查是否有权限 */ public class ButtonProxy implements IFunction { //持有被代理对象的引用 private IFunction function; //定义角色名称 private String roleName; public ButtonProxy(IFunction function,String roleName){ this.function = function; this.roleName = roleName; } @Override public String getBtnName() { return null; } @Override public void click() { if("admin".equals(roleName)){ System.out.println("权限校验合法"); function.click(); }else{ System.out.println("没有权限点击"+function.getBtnName()); } } } package com.statics.proxy; /** * 静态代理测试类 */ public class TestStaticsProxy { public static void main(String[] args) { //创建提交按钮 IFunction target = new Button("提交按钮"); //没有代理之前的调用 target.click(); System.out.println("===================="); //创建代理对象 IFunction proxy = new ButtonProxy(target,"admin"); //IFunction proxy = new ButtonProxy(target,"guest"); //代理后点击调用方法 proxy.click(); } }
4.2、动态代理
4.2.1、JDK动态代理:创建代理对象,然后代理对象调用回调函数,最后完成代理对被代理对象增强
package com.dynamic.proxy; public interface IFunction { void click(); void dbClick(); String getName(); } package com.dynamic.proxy; public class Window implements IFunction { private String name; public Window(String name){ this.name = name; } @Override public void click() { System.out.println(this.name+"被单击了"); } @Override public void dbClick() { System.out.println(this.name+"被双击了"); } @Override public String getName() { return name; } } package com.dynamic.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * JDK动态代理:只能代理实现接口的类
* 如果要加注解,需要在接口上面加注解,不在实现类上加。否则Method.isAnnotationPresent(Xxx.class)找不到 */ public class ObjectProxy { //持有目标代理类对象 private Object target; public ObjectProxy(){ } public ObjectProxy(Object target){ this.target = target; } /** * 定义生成目标对象代理对象的方法 * 生成代理对象 * Proxy.newProxyInstance第三个参数是回调,代理对象执行 */ public Object createProxy(){ return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),new Handle()); } /*** * 回调处理的内部类 */ private class Handle implements InvocationHandler{ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { validateLogin(); validateRole(); Object obj = method.invoke(target,args); requestData(); responseData(); return obj; } } private void validateLogin(){ System.out.println("验证登录,验证成功"); } private void validateRole(){ System.out.println("验证角色,验证成功"); } private void requestData(){ System.out.println("请求服务器端数据"); } private void responseData(){ System.out.println("返回服务器端数据"); } } package com.dynamic.proxy; public class TestDynamicProxy { public static void main(String[] args) { //创建目标代理对象 IFunction target = new Window("模态窗口"); target.click(); target.dbClick(); System.out.println("===================="); //创建一个代理对象 ObjectProxy op = new ObjectProxy(target); IFunction proxy = (IFunction) op.createProxy(); proxy.click(); System.out.println("===================="); proxy.dbClick(); } }
5、cglib代理
JDK代理要求被代理的类必须实现接口,有很强的局限性。而CGLIB动态代理则没有此类强制性要求。简单的说,CGLIB会让生成的代理类继承被代理类,并在代理类中对代理方法进行强化处理(前置处理、后置处理等)。在CGLIB底层,其实是借助了ASM这个非常强大的Java字节码生成框架。
package com.cglib.proxy; /** * 被代理类 */ public class Button { public void click() { System.out.println("按钮被点击了"); } } package com.cglib.proxy; import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; import java.lang.reflect.Method; /** * MethodInterceptor拦截 */ public class ButtonMethodInterceptor implements MethodInterceptor { /** * * @param o 被代理对象 * @param method 代理增加方法 * @param objects 代理方法参数 * @param methodProxy 代理方法 * @return * @throws Throwable */ @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("before:权限检查"); Object object = methodProxy.invokeSuper(o,objects); System.out.println("after:权限检查通过"); return object; } } package com.cglib.proxy; import org.springframework.cglib.proxy.Enhancer; /** * Cglib动态代理创建 */ public class ButtonProxy { public Object createCglibProxy(){ Enhancer enhancer=new Enhancer(); enhancer.setSuperclass(Button.class); enhancer.setCallback(new ButtonMethodInterceptor()); Button proxy = (Button)enhancer.create(); return proxy; } public static void main(String[] args) { Button buttonProxy = (Button)new ButtonProxy().createCglibProxy(); buttonProxy.click(); } }