温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Java中怎么利用接口来创建代理

发布时间:2021-06-11 14:02:07 来源:亿速云 阅读:469 作者:Leah 栏目:开发技术

Java中怎么利用接口来创建代理?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

首先创建工厂bean,就是用来返回代理的FactoryBean

import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.annotation.Autowired; import java.lang.reflect.Proxy; public class HttpProxyFactoryBean<T> implements FactoryBean<T> {     /**      *【注意】      * 这里之所以可以进行自动装配,是因为当前的这个HttpProxyFactoryBean是会被注册到Spring中的      * 只不过它的注册方式 跟一般的不一样(一般会在类上,加一个如@Component、@Service这样的注解 )      * 它是通过注册BeanDefinition的方式注册的,可能会注册多个,而其中的每一个HttpProxyFactoryBean实例都会被自动装配同一个HttpProxyInvocationHandler实例      *      * 也有等价的做法是:      * 利用ApplicationContextAware接口的setApplicationContext获取到applicationContext,      * 然后把applicationContext 作为属性设置到当前类中      *  再利用applicationContext的getBean方法来获取InvocationHandler的实例      */     @Autowired     private HttpProxyInvocationHandler httpProxyInvocationHandler;     private Class<T> rpcInterface;     public HttpProxyFactoryBean(Class<T> rpcInterface){         this.rpcInterface = rpcInterface;     }     @Override     public T getObject() throws Exception {         //这里应该放ComputerService接口         return (T)Proxy.newProxyInstance(rpcInterface.getClassLoader(),new Class[]{rpcInterface} ,httpProxyInvocationHandler);     }     @Override     public Class<?> getObjectType() {         return rpcInterface;     } }

每一个动态代理类都必须要实现InvocationHandler这个接口

每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用。

我们可以直接将实现InvocationHandler的实现类注入spring容器中,然后每一个接口走同一个innvoke方法,当然也可以每一个都new一个,然后可以在构造方法中塞入特定的一些参数。我这边因为对应的每一个代理没啥特殊的就走同一个了:
定义一些参数,请求的urlproxy.serverUrl,和请求添加的项目,proxy.project

import cn.hutool.http.HttpRequest; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.util.Collection; import java.util.HashMap; import java.util.Map; /**  * @Description 把服务方法的调用转换为对远程服务的http请求  * @Version  */ @Component public class HttpProxyInvocationHandler implements InvocationHandler {     @Value("${proxy.serverUrl}")     private String serverUrl;     @Value("${proxy.project}")     private String serverProject;     @Override     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {         Class<?> declaringClass = method.getDeclaringClass();         if (Object.class.equals(declaringClass)) {             return method.invoke(this, args);         }         String methodName = method.getName();         String name = method.getDeclaringClass().getName();         //拼接请求地址         String url = serverUrl + name + "/" + methodName; //        String url = "http://test:8080/soa/com.rdd.TestService/createActivity";         HashMap<String, String> paramMap = new HashMap<>();      //        String result = HttpRequest.post(url).headerMap(paramMap, true).body("[" + JSONObject.toJSONString(args) + "]").execute().body();         String result = HttpRequest.post(url).headerMap(paramMap, true).body(JSONObject.toJSONString(args)).execute().body();         System.out.println(">>>" + url + "的响应结果为:" + result);         //将响应结果转换为接口方法的返回值类型         Class<?> returnType = method.getReturnType();         if (returnType.isPrimitive() || String.class.isAssignableFrom(returnType)) {             if (returnType == int.class || returnType == Integer.class) {                 return Integer.valueOf(result);             } else if (returnType == long.class || returnType == Long.class) {                 return Long.valueOf(result);             }             return result;         } else if (Collection.class.isAssignableFrom(returnType)) {             return JSONArray.parseArray(result, Object.class);         } else if (Map.class.isAssignableFrom(returnType)) {             return JSON.parseObject(result, Map.class);         } else {             return JSONObject.parseObject(result, returnType);         }     } }

最后后将对应的工厂bean封装成bean定义,注入到spring容器中

我们的接口一般都是jar形式的,我就简单的写在一个proxy.txt文件中,然后去读取对应的接口全路径,注入到spring容器中,当然也可以通过扫描某个包,自定义注解等等方式实现。

import cn.hutool.core.io.file.FileReader; import org.apache.commons.lang.StringUtils; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.*; import org.springframework.context.annotation.PropertySource; import org.springframework.stereotype.Component; import java.util.HashSet; import java.util.List; import java.util.Set; /**  * @Title:bean工厂的后置处理器,用于动态注册bean  * @Date 2021/3/23 10:13  * @Description  * @Version  */ @Component @PropertySource("classpath:application.properties") public class HttpProxyRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {     /**      * 该方法用来注册更多的bean到spring容器中      *      * @param beanDefinitionRegistry      * @throws BeansException      */     @Override     public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {         //默认UTF-8编码,可以在构造中传入第二个参数做为编码         FileReader fileReader = new FileReader("proxy.txt");         List<String> classStrList = fileReader.readLines();         Set<Class<?>> proxyClazzSet = new HashSet<>();         for (String s : classStrList) {             if (StringUtils.isBlank(s)) {                 continue;             }             try {                 Class<?> aClass = Class.forName(s);                 proxyClazzSet.add(aClass);             } catch (ClassNotFoundException e) {                 e.printStackTrace();             }         }         for (Class<?> targetClazz : proxyClazzSet) {             BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(targetClazz);             GenericBeanDefinition definition = (GenericBeanDefinition) beanDefinitionBuilder.getRawBeanDefinition();             //设置构造方法的参数  对于Class<?>,既可以设置为Class,也可以传Class的完全类名             //definition.getConstructorArgumentValues().addGenericArgumentValue(targetClazz);             definition.getConstructorArgumentValues().addGenericArgumentValue(targetClazz.getName());             //Bean的类型,指定为某个代理接口的类型             definition.setBeanClass(HttpProxyFactoryBean.class);             //表示 根据代理接口的类型来自动装配             definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);             beanDefinitionRegistry.registerBeanDefinition(targetClazz.getName(),definition);         }     }     @Override     public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {     } }

关于Java中怎么利用接口来创建代理问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注亿速云行业资讯频道了解更多相关知识。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI