描述总是比较抽象,还是看实际例子比较好理解
例子
InvocationHandler接口的实现类
public class CommonInvocationHandler implements InvocationHandler { //被代理的对象 private Object proxied; public CommonInvocationHandler(Object proxied) { this.proxied = proxied; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //在调用被代理对象的方法前做一些事情 System.out.println("before doing something"); //调用被代理对象的方法 Object result = method.invoke(proxied, args); //在调用被代理对象的方法后做一些事情 System.out.println("after doing something");; return result; } } |
Main
public class Main { public static void main(String[] args) { //被代理的对象 Water water = new Water(); //动态获取代理对象 Drink waterProxy = (Drink) Proxy.newProxyInstance(water.getClass().getClassLoader(), water.getClass().getInterfaces(), new CommonInvocationHandler(water)); //通过代理对象调用方法 waterProxy.drink(); } } |
输出结果
before doing something
drink water
after doing something
也可以不要具体的被代理对象,但是必须有相应的接口(没有实现接口的类可以使用cglib实现动态代理)才可以动态获取代理对象。像最近比较火的Retrofit就直接通过声明好的接口使用动态代理进行网络请求。
例子
简单的模拟一下retrofit
POST注解
//Post请求注解 @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface POST { String value() default ""; } |
Query注解
//Post请求注解 @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface POST { String value() default ""; } |
Service接口
public interface Service { //用POST注解声明请求的方式和相对路径 @POST("/login") //@Query注解声明请求的参数名 void login(@Query("username")String username, @Query("password")String password); } |
Main
public class Main { public static void main(String[] args) { // 动态获取Service接口的代理 Service service = (Service) Proxy.newProxyInstance(Service.class.getClassLoader(), new Class[] { Service.class }, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 通过注解获取请求的相对路径 String retativePath = ((POST) method.getAnnotations()[0]).value(); System.out.println("relative path: " + retativePath); // 获取参数的注解 Annotation[][] parameterAnnotations = method.getParameterAnnotations(); // 通过参数的注解获取请求参数 for (int i = 0; i < parameterAnnotations.length; i++) { if (parameterAnnotations[i].length != 0) { for (int j = 0; j < parameterAnnotations[i].length; j++) { Query query = (Query) parameterAnnotations[i][j]; System.out.println(query.value() + ": " + args[i].toString()); } } } return null; } }); // 调用代理对象的方法 service.login("hello", "world"); } } |