代理与被代理类之间通过接口来进行联系。
- package com.example.Demo;
-
- public class SuperStart implements Start {
- private String name;
-
- public SuperStart(String name) {
- this.name = name;
- }
-
- public String sing(String name) {
- System.out.println(this.name + "正在唱:" + name);
- return "谢谢谢谢";
- }
- public void dance() {
- System.out.println(this.name + "正在跳舞");
- }
- }
代理类
在代理类中,创建一个生成代理对象的方法,其中将被代理对象作为参数传入,即指定产生谁的代理,其实是通过最后将被代理对象作为参数传入invoke()方法中而实现的,代理对象通过Proxy.newProxyInstance()方法创建,该方法中的三个参数的作用都在代码注解中有,自己体会。
- package com.example.Demo;
-
- import java.lang.reflect.InvocationHandler;
- import java.lang.reflect.Method;
-
- public class Proxy {
- public static Start createProxy(SuperStart superStart) // 指定该方法产生谁的代理
- {
- // 创建一个代理对象
- /* ClassLoader loader,
- Class>[] interfaces,
- InvocationHandler h
- 参数1 ClassLoader:用于指定一个类加载器,一般是当前类的类加载器,用于加载代理类
- 参数2 Class>[] :指定代理类实行的接口列表,代理类与被代理类实现相同的接口以便能够代理被代理对象中的方法,这些接口用于指定代理长什么样子,也就是有哪些方法,被代理对象所属类,应该实现该接口,创建的代理实例应该转换为该接口类型
- 参数3 InvocationHandler :用于指定生成的代理对象需要干什么事情,一般是直接创建一个接口的匿名内部类对象
- */
- Start startProxy = (Start) java.lang.reflect.Proxy.newProxyInstance(Proxy.class.getClassLoader(),
- new Class[]{Start.class}, new InvocationHandler() {
- @Override // 回调方法
- // 该方法指定代理对象所要干的事情
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- // 其中proxy指的是startProxy
- // method指的是表示被调用的方法对象
- // args表示被调用方法的参数数组
- if (method.getName().equals("sing")) {
- System.out.println("需要唱歌,需要话筒");
- } else if (method.getName().equals("dance")) {
- System.out.println("需要跳舞,需要准备场地");
- }
- return method.invoke(superStart, args);//通过反射机制,调用superStart对象的method方法,并传递args作为方法的参数。这样就实际执行了被代理对象的方法。
- }
- });
- return startProxy; // 返回生成的代理对象
- }
- }
-
接口类
- package com.example.Demo;
-
- public interface Start {
- String sing(String name);
-
- void dance();
- }
测试类
- package com.example.Demo;
-
- public class Test {
- public static void main(String[] args) {
- SuperStart superStart = new SuperStart("法老");
- Start startProxy = Proxy.createProxy(superStart); // 生成superStart对象的代理对象
- System.out.println(startProxy.sing("会魔法的老人"));
- startProxy.dance();
- }
- }
运行测试类结果如下
- package com.example.Proxy;
-
- public class UserServiceImpl implements UserService {
- @Override
- public void login(String loginName, String password) throws Exception {
- long starTime = System.currentTimeMillis();
- if ("admin" == loginName && "123456" == password) {
- System.out.println("登陆成功");
- } else {
- System.out.println("登陆失败");
- }
- Thread.sleep(1000);
- long endTime = System.currentTimeMillis();
- System.out.println("login方法耗时:" + (endTime - starTime) / 1000 + "s");
- }
-
- @Override
- public void deleteUser() throws Exception {
- long starTime = System.currentTimeMillis();
- System.out.println("成功删除1个用户");
- Thread.sleep(1500);
- long endTime = System.currentTimeMillis();
- System.out.println("deleteUser方法耗时:" + (endTime - starTime) / 1000 + "s");
- }
-
- }
- package com.example.Proxy;
-
- public interface UserService {
- // 登录功能
- void login(String loginName, String password) throws Exception;
-
- // 删除用户
- void deleteUser() throws Exception;
-
- }
存在的问题
在接口实现类中存在许多与业务不相关且重复的代码逻辑,这部分代码可以交给代理=对象处理
代理如下
- package com.example.Proxy;
-
- import java.lang.reflect.InvocationHandler;
- import java.lang.reflect.Method;
-
- public class Proxy {
- public static UserService createProxy(UserService userService) {
- UserService UserServiceProxy = (UserService) java.lang.reflect.Proxy.newProxyInstance(Proxy.class.getClassLoader(), new Class[]{UserService.class}, new InvocationHandler() {
- @Override
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- if (method.getName().equals("login") || method.getName().equals("deleteUser")) {
- long starTime = System.currentTimeMillis();
- Object rs = method.invoke(userService, args);
- Thread.sleep(1000);
- long endTime = System.currentTimeMillis();
- System.out.println(method.getName() + "方法耗时:" + (endTime - starTime) / 1000 + "s");
- return rs;
- } else {
- Object rs = method.invoke(userService, args);
- return rs;
- }
- }
- });
- return UserServiceProxy;
- }
- }