设计模式代理设计模式Proxy 1.代理模式参考资料:
1.重学设计模式书籍
2.https://www.cnblogs.com/tera/p/13911819.html
3.参考 :http://www.mayikt.com/front/couinfo/194/0
代理模式控制对象的行为,
对对象行为增加(装饰者模式也可以对象的行为进行增加).属于结构行模式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qUTG66dk-1635928910217)(…jdk-proxyimg 1.png)]
通俗来说,就是我想点份外卖,但是手机没电了,于是我让同学用他手机帮我点外卖。在这个过程中,其实就是我同学(代理对象)帮我(被代理的对象)代理了点外卖(被代理的行为),在这个过程中,同学可以完全控制点外卖的店铺、使用的APP,甚至把外卖直接吃了都行**(对行为的完全控制)**。
2.JDK代理基本实现[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CKnwdOfg-1635928910221)(…jdk-proxyimg 3.png)]
JDK动态代理, 静态代理需要自己编写代理类。
public interface AbStractSubject {
String showInfo();
}
public class SubjectImpl implements AbStractSubject{
@Override
public String showInfo() {
return "jdk动态代理技术基本使用";
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JdkInvocationHandler implements InvocationHandler {
private Object target;
public JdkInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("开始执行前系统当前时间:" + System.currentTimeMillis());
Object invoke = method.invoke(target, args);//返回执行目标方法的返回值
System.out.println("执行结果:" + invoke);
System.out.println("结束执行后系统的时间" + System.currentTimeMillis());
return invoke;
}
public T getProxy() {
//loader – 定义代理类的类加载器
//接口 - 代理类要实现的接口列表
//h – 将方法调用分派到的调用处理程序
return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
}
public class JDKProxyTest {
public static void main(String[] args) {
AbStractSubject abStractSubject = new JdkInvocationHandler(new SubjectImpl()).getProxy();
abStractSubject.showInfo();
}
}
3.案例场景模拟JDK动态代理的另一种写法
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; public class JdkProxy { private Object target; public JdkProxy(Object target) { this.target = target; } publicT getProxyObj() { InvocationHandler handler = (proxy, method, args) -> { System.out.println("1.方法前执行~~~~~"); Object invoke = method.invoke(target, args); if (invoke != null) { System.out.println(invoke); } System.out.println("2.方法后执行~~~~~~"); return invoke; }; return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), handler); } } public class JDKProxyTest2 { public static void main(String[] args) { AbStractSubject proxyObj = new JdkProxy(new SubjectImpl()).getProxyObj(); proxyObj.userInfo(); System.out.println("-------------------------------"); proxyObj.showInfo(); } }
- 使⽤过的⼀些中间件例如;RPC框架,在拿到jar包对接⼝的描述后,中间件会在服务启动的时候⽣成对应的代理类,当调⽤接⼝的时候,实际是通过代理类发出的socket信息进⾏通过
- 另外像我们常⽤的 MyBatis ,基本是定义接⼝但是不需要写实现类,就可以对 xml 或者⾃定义注解⾥的 sql 语句进⾏增删改查操作。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-04FhXy6S-1635928910224)(…jdk-proxyimg 2.png)]
3.1 代理类模式实现Mapper代理import com.example.proxy.anotaion.Select;
public interface IUserDao {
@Select("select * from mayikt_type where id = #{uId}")
String queryUserInfo(String uId);
}
import com.example.proxy.anotaion.Select; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.FactoryBean; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; public class MapperFactoryBeanimplements FactoryBean { private Logger logger = LoggerFactory.getLogger(MapperFactoryBean.class); private Class mapperInterface; public MapperFactoryBean(Class mapperInterface) { this.mapperInterface = mapperInterface; } @Override public T getObject() throws Exception { InvocationHandler handler = (proxy, method, args) -> { Select select = method.getAnnotation(Select.class); logger.info("SQL:{}", select.value().replace("#{uId}", args[0].toString())); return args[0] + ",沉淀、分享、成⻓,让⾃⼰和他 ⼈都能有所收获!"; }; return (T) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[] {mapperInterface}, handler); } @Override public Class> getObjectType() { return mapperInterface; } @Override public boolean isSingleton() { return true; } }
import com.example.proxy.mapper.IUserDao;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.GenericBeanDefinition;
public class RegisterBeanFactory implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(MapperFactoryBean.class);
beanDefinition.setScope("singleton");
beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(IUserDao.class);
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(beanDefinition, "userDao");
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException { }
}
@SpringBootTest
class MayiktProxyDemoApplicationTests {
Logger logger = LoggerFactory.getLogger(MayiktProxyDemoApplicationTests.class);
@Test
void contextLoads() {
BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring-config.xml");
IUserDao userDao = beanFactory.getBean("userDao", IUserDao.class);
String res = userDao.queryUserInfo("1");
logger.info("测试结果:{}", res);
}
}
3.2 对接口方法代理SpringAop 中使用jdk代理和cglib代理, 被代理类实现抽象主题接口实现接口 采用的是jdk代理; 被代理类继承抽象的主题角色采用cglib代理
在一些rpc框架中,客户端只需要关注接口的的调用,而具体的远程请求则由框架内部实现。
public interface OrderInterface {
void addOrder(String name);
}
import com.example.proxy.util.HttpClientUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class SimpleRpcframe {
Logger logger = LoggerFactory.getLogger(SimpleRpcframe.class);
public static T getRemoteProxy(Class service) {
return (T) Proxy.newProxyInstance(service.getClassLoader(),
new Class>[]{service},
new RpcHandler(service));
}
static class RpcHandler implements InvocationHandler {
Logger logger = LoggerFactory.getLogger(RpcHandler.class);
private Class service;
public RpcHandler(Class service) {
this.service = service;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//Object result = RemoteCallUtility.request(service.getName(), method.getName(), args);
String name = service.getName();
String name1 = method.getName();
Object result = null;
//logger.info("参数args:{}",args);
//
//JSonArray jsonArray = JSON.parseArray(args.toString());
//logger.info("转换后的jsonArray:{}",jsonArray);
result = HttpClientUtil.doPost("http://www.baidu.com", null);
return result;
}
}
}
public class RpcInvoker {
public void invoke(String name) {
OrderInterface order = SimpleRpcframe.getRemoteProxy(OrderInterface.class);
order.addOrder(name);
}
}
@Test
void proxyInterface(){
RpcInvoker rpcInvoker = new RpcInvoker();
rpcInvoker.invoke("zhongxu");
}



