网站域名购买后能修改吗重庆设计公司有哪些
代理模式
代理模式使用代理对象来代替真实对象的访问,在不修改原有对象的前提下,提供额外的操作,扩展目标对象的功能。代理模式分为静态代理和动态代理。
静态代理
手动为目标对象中的方法进行增强,通过实现相同接口重写方法进行增强。非常不灵活,当对象中新增方法时,代理类同样需要增加代理方法。静态代理是在代码编译时生成的代理类
实现步骤
- 定义接口和实现类
 - 定义代理类实现接口
 - 将被代理类注入,重写方法,在方法中增强
 
代码展示
-  
接口
public interface Image {void display(String name); } -  
实现类
public class RealImage implements Image {@Overridepublic void display(String name) {System.out.println(name + " display");} } -  
代理类
public class StaticProxy implements Image {private RealImage realImage;@Overridepublic void display(String name) {realImage = new RealImage();System.out.println("start");realImage.display(name);System.out.println("end");}public static void main(String[] args) {Image image = new StaticProxy();image.display("图片");} } 
静态代理简单并且局限性太高,一般没有人使用
动态代理
相较于静态代理,动态代理更加灵活,可以被多个类创建统一代理类。针对实现类和接口分别有JDK动态代理和CGLIB动态代理。动态代理是在运行时动态生成代理类并加载到JVM中去的。
JDK动态代理
JDK动态代理是为已经实现接口的类创建代理类。核心是**InvocationHandler接口和Proxy类。Proxy类用于生成代理对象,InvocationHandler接口用于自定义处理逻辑。当我们用Proxy类中的newProxyInstance()方法生成的动态代理对象调用方法时,这个方法的调用会转发到InvocationHandler接口中的invoke**方法中来调用。
Proxy 类中使用频率最高的方法是:newProxyInstance() ,这个方法主要用来生成一个代理对象。
    public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)throws IllegalArgumentException{......}
 
这个方法一共有 3 个参数:
- loader :类加载器,用于加载代理对象。
 - interfaces : 被代理类实现的一些接口;
 - h : 实现了 
InvocationHandler接口的对象; 
要实现动态代理的话,还必须需要实现InvocationHandler 来自定义处理逻辑。 当我们的动态代理对象调用一个方法时,这个方法的调用就会被转发到实现InvocationHandler 接口类的 invoke 方法来调用。
public interface InvocationHandler {/*** 当你使用代理对象调用方法的时候实际会调用到这个方法*/public Object invoke(Object proxy, Method method, Object[] args)throws Throwable;
}
 
invoke() 方法有下面三个参数:
- proxy :动态生成的代理类
 - method : 与代理类对象调用的方法相对应
 - args : 当前 method 方法的参数
 
实现步骤
- 定义接口和实现类
 - 自定义**
InvocationHandler并重写invoke**方法,在方法中调用被代理的方法并实现自定义处理逻辑 - 通过 
Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)方法创建代理对象 - 使用代理对象进行方法调用
 
代码展示
-  
接口和实现类同上
 -  
InvocationHandler
/*** @author linmeng* @date 2023/2/22 00:42*/ public class JdkInvocationHandler implements InvocationHandler {/*** 被代理类**/private Object target;public JdkInvocationHandler(Object target) {this.target = target;}/*** @Author linmeng* @Description * @date 2023/2/24 15:57* @param proxy 动态生成的代理类* @param method 代理方法* @param args 方法参数* @return java.lang.Object**/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("调用方法前打印方法名称;" + method.getName());Object res = method.invoke(target, args);System.out.println("调用方法后打印方法名称;" + method.getName());return res;} } -  
代理对象生成
import java.lang.reflect.Proxy;/*** @author linmeng* @date 2023/2/22 00:44*/ public class JDKProxy {public static Object getProxy(Object target) {return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new JdkInvocationHandler(target));}} -  
测试
import org.junit.Test;/*** @author linmeng* @date 2023/2/22 00:50*/public class JdkTest {@Testpublic void jdkTest(){Image proxy = (Image) JDKProxy.getProxy(new RealImage());proxy.display("图片");} 
CGLIB动态代理
当类没有实现接口时,是不能用JDK动态代理的。这个时候可以用CGLIB动态代理,他是通过继承的方式实现代理。
**在 CGLIB 动态代理机制中 MethodInterceptor 接口和 Enhancer 类是核心。**通过实现MethodInterceptor接口中的intercept方法自定义处理逻辑,Enhancer类创建代理类。
你需要自定义 MethodInterceptor 并重写 intercept 方法,intercept 用于拦截增强被代理类的方法。
public interface MethodInterceptor
extends Callback{// 拦截被代理类中的方法public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args,MethodProxy proxy) throws Throwable;
}
 
- obj : 被代理的对象(需要增强的对象)
 - method : 被拦截的方法(需要增强的方法)
 - args : 方法入参
 - proxy : 用于调用原始方法
 
你可以通过 Enhancer类来动态获取被代理类,当代理类调用方法的时候,实际调用的是 MethodInterceptor 中的 intercept 方法。
实现步骤
- 实现类
 - 自定义
MethodInterceptor并重写intercept方法,自定义增强逻辑 - 通过 
Enhancer中的create()方法创建代理对象 - 使用代理对象调用方法
 
代码展示
-  
实现类
public class RealImage2 {public void display(String name) {System.out.println(name + " display");} } -  
自定义
MethodInterceptor并重写intercept方法/*** @author linmeng* @date 2023/2/24 14:10*/ public class CGLIBInterceptor implements MethodInterceptor {/*** @param o 被代理对象* @param method 被拦截的方法* @param objects 方法入参* @param methodProxy 用于调用元素方法* @return java.lang.Object* @Author linmeng* @Description* @date 2023/2/24 14:11**/@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("调用方法前打印方法名称;" + method.getName());Object res = methodProxy.invokeSuper(o, objects);System.out.println("调用方法后打印方法名称;" + method.getName());return res;} } -  
通过
Enhancer中的create()方法创建代理对象import net.sf.cglib.proxy.Enhancer;/*** @author linmeng* @date 2023/2/24 14:15*/ public class CGLIBProxy {public static Object getProxy(Class<?> clazz) {// 动态代理增强类Enhancer enhancer = new Enhancer();// 类加载器enhancer.setClassLoader(clazz.getClassLoader());// 被代理类enhancer.setSuperclass(clazz);// 增强类enhancer.setCallback(new CGLIBInterceptor());// 代理类创建return enhancer.create();} } -  
使用
import org.junit.Test;/*** @author linmeng* @date 2023/2/22 00:50*/ public class CGLIBTest {@Testpublic void cglibTest(){RealImage2 proxy = (RealImage2) CGLIBProxy.getProxy(RealImage2.class);proxy.display("图片");} } 
参考链接
- Java设计模式:Proxy(代理)模式
 - Java 代理模式详解
 - Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass
 
