代理模式简单实现
代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.
好处:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能.
代理模型的三种方式
1. 静态代理
2. 动态代理
JDK动态代理
CGLIB动态代理
一、静态代理
在不修改目标对象方法的基础上,对目标对象方法进行扩展。
package com.lemon.service; //Service接口 public interface UserService { void save(); void delete(); void update(); }
package com.lemon.service.impl; import com.lemon.service.UserService; //Service实现 public class UserServiceImpl implements UserService { @Override public void save() { System.out.println("新增用户"); } @Override public void delete() { System.out.println("删除用户"); } @Override public void update() { System.out.println("修改用户"); } }
package com.lemon.a_staticproxy; import com.lemon.service.UserService; /** * 静态代理类 * 实现日志扩展功能 *要求: *1)和目标(类)实现同样的接口 *2)在静态代理类中传入目标对象实例,以便调用目标对象的方法 *3)可以在静态代理类的方法中添加代理逻辑代码 */ public class LogProxy implements UserService{ //接收目标对象实例 private UserService userService; //使用构造方法传入目标对象实例 public LogProxy(UserService userService){ this.userService = userService; } @Override public void save() { System.out.println("before=====save"); //调用目标对象的方法 userService.save(); System.out.println("after=====save"); } @Override public void delete() { System.out.println("before=====save"); //调用目标对象的方法 userService.delete(); System.out.println("after=====save"); } @Override public void update() { System.out.println("before=====save"); //调用目标对象的方法 userService.update(); System.out.println("after=====save"); } }
package com.lemon.a_staticproxy; import com.lemon.service.UserService; import com.lemon.service.impl.UserServiceImpl; //测试 public class Test { public static void main(String[] args) { //使用静态代理模式 //1.创建目标对象 UserService userService = new UserServiceImpl(); //2.创建静态代理类对象 UserService proxy = new LogProxy(userService); //3.调用代理类的方法 proxy.save(); proxy.update(); proxy.delete(); } }
静态代理的缺点:
1)一个静态代理类只能代理一个目标类
2)静态代理类的每个方法都需要编写重复的代理逻辑,代码比较冗余
二、JDK动态代理
前提:目标对象有接口的情况
package com.lemon.b_jdk_dynamic_proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * 用于生成JDK动态代理对象的工具类 */ public class LogProxy { /** * 生成JDK动态代理对象的方法 * * 返回值:生成的JDK动态代理对象 * 参数:target, 传入目标对象 */ public static Object getProxy(Object target){ /** * 参数一:类加载器,JDK动态代理的底层使用类加载器来生成的一个动态类的。通常传入当前类的类加载器即可!!!(LogProxy.class.getClassLoader()) * 参数二:目标对象的接口列表(所有接口),通常使用目标对象获取接口列表(target.getClass().getInterfaces()) * 参数三:接口。 该用于编写 代理类的代理逻辑代码。通常我们要提供InvocationHandler接口的实现类(匿名内部类的方式提供) */ return Proxy.newProxyInstance( LogProxy.class.getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { /** * invoke方法:用于编写 代理类的代理逻辑代码。 * invoke方法在什么时候会被调用? * 该方法会在调用JDK代理对象的每个方法的时候被执行!!!!! * * @param proxy: 生成JDK动态代理对象 * @param method: 目标对象的执行方法的对象 * @param args: 目标对象的方法参数列表 * @return 返回值:目标对象方法执行后的返回结果 * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //获取目标对象的方法名称 String methodName = method.getName(); System.out.println("before======"+methodName); //获取方法的参数列表 /* if(args!=null) System.out.println(Arrays.asList(args));*/ //调用目标对象的方法 /** * 参数一:执行的对象(必须传入目标对象,不能传入代理对象,否则会死循环) * 参数二:方法的参数列表 */ Object result = method.invoke(target,args); System.out.println("after======"+methodName); return result; } } ); } }
package com.lemon.b_jdk_dynamic_proxy; import com.lemon.service.UserService; import com.lemon.service.impl.UserServiceImpl; /** * 演示JDK动态代理 */ public class Demo { public static void main(String[] args) { //1.创建目标对象 UserService userService = new UserServiceImpl(); //2.创建静态代理类对象 UserService proxy = (UserService) LogProxy.getProxy(userService); //3.调用代理类的方法 proxy.save(); proxy.delete(); proxy.update(); } }
三、
<!-- 导入spring-core(包含cglib依赖) --> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>5.0.2.RELEASE</version> </dependency> </dependencies>
package com.lemon.c_cglib_dynamic_proxy; import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; import java.lang.reflect.Method; /** * 用于生成Cglib代理对象的工具类 */ public class LogProxy { /** * 生成Cglib代理对象 * 返回值:生成的Cglib子类代理对象 * 参数:目标对象(目标对象没有接口) */ public static Object getProxy(Object target){ /** * 方法返回值:生成的Cglib子类代理对象 * 参数一:目标对象的类型(target.getClass()) (其实目标对象的类型就是Cglib代理对象 的 父类) * 参数二:MethodInterceptor接口,用于编写 代理对象的代理逻辑代码。通常提供MethodInterceptor接口的匿名内部即可 */ return Enhancer.create( target.getClass(), new MethodInterceptor() { /** * intercept方法:在调用代理对象的每个方法的时候会执行 * @param proxy: 生成的代理对象 * @param method: 目标对象的方法对象 * @param args: 目标对象的方法参数列表 * @param methodProxy: 代理对象的方法对象 * @return * @throws Throwable */ @Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { //获取目标对象的方法名称 String methodName = method.getName(); System.out.println("before======"+methodName); /** * 调用目标对象的方法 */ //方式一:直接使用目标对象 调用 目标对象的方法 Object result = method.invoke(target,args); //方式二:使用代理类(子类)调用 目标对象(父类)的方法 //invokeSuper: 调用父类的方法 //Object result = methodProxy.invokeSuper(proxy,args); System.out.println("after====="+methodName); return result; } } ); } }
package com.lemon.c_cglib_dynamic_proxy; import com.lemon.b_jdk_dynamic_proxy.LogProxy; import com.lemon.service.UserService; import com.lemon.service.impl.UserServiceImpl; /** * 演示JDK动态代理 */ public class Demo2 { public static void main(String[] args) { //1.创建目标对象 UserService userService = new UserServiceImpl(); //2.创建静态代理类对象 UserService proxy = (UserService) LogProxy.getProxy(userService); //3.调用代理类的方法 proxy.save(); proxy.delete(); proxy.update(); } }