代理模式
一、什么是代理
代理对象代替被代理对象干活
二、代理作用
对被代理对象方法的增强
三、代理的种类:静态代理、动态代理
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(); } }
感谢您的阅读,您的支持是我写博客动力。

浙公网安备 33010602011771号