介绍
代理模式是一种非常好理解的设计面试:当前对象不愿意干的,没法干的东西委托给别的对象来做
用代码描述代理模式
一个程序员接口,他每天写代码
ndb也是一个程序员
静态代理
ndb想请一个程序员大V给自己点赞,已得到人气和money
透明代理(普通代理)
ndb想让程序员大v只做ndb的生意
代理类自定义方法
大v看到ndb赚大钱,决定加钱
动态代理
ndb 决定不请大v,而请水军(水军便宜,只要点赞就行)
public class Java3y implements Programmer {
@Override
public void coding() {
System.out.println("Java3y最新文章:......给女朋友讲解什么是代理模式.......");
}
}
动态代理
Java提供一个Proxy类,调用它的newinstance方法可以生成某个对象的地理对象,需要三个参数:
- 参数一:生成代理对象使用哪个类装载器【一般我们使用的是被代理类的装载器】
- 参数二:生成哪个对象,通过接口指定【指定要被代理类的接口】
- 参数三:生成的代理对象的方法里干什么事【实现handler接口,我们想怎么实现就怎么实现】
在编写动态代理之前,要明确几个概念
- 代理对象拥有目标对象相同的方法【参数二指定了对象的接口,代理对象会实现接口的所有方法】
- 用户调用代理对象的什么方法,都是在调用处理器的invoke方法【被拦截】
- 使用jdk动态代理必须要有接口【参数二日需要接口】
上面也说了:代理对象会实现接口的所有方法,这些实现的方法交由我们的handler来处理
所有通过动态代理实现的方法全部通过invoke()调用
动态代理的调用过程
静态代理和动态代理的区别
- 静态代理需要自己写代理类–代理类需要实现与目标对象相同的接口
- 而动态代理不需要自己编写代理类–动态生成
使用静态代理类时:
如果目标对象有很多方法的话,那我们还是得一一实现,比较麻烦
使用动态代理时:
代理对象的生成,时利用jdkapi,动态地在内存中构建代理对象(需要我们指定创建,代理对象/目标对象 实现的接口类型),并且默认实现接口的全部方法
典型应用
我们之前写过中文过滤器的时候,需要使用包装设计模式来设计一个request类,如果不是提供servlet提供了实现类给我们,我们使用包装设计模式会比较麻烦
现在我们学习了动态代理,动态代理就是拦截直接访问对象,可以给对象进行增强的一项功能,
中文过滤器
public void doFilter(final ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
final HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
response.setContentType("text/html;charset=UTF-8");
request.setCharacterEncoding("UTF-8");
//放出去的是代理对象
chain.doFilter((ServletRequest) Proxy.newProxyInstance(CharacterEncodingFilter.class.getClassLoader(), request.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//判断是不是getParameter方法
if (!method.getName().equals("getParameter")) {
//不是就使用request调用
return method.invoke(request, args);
}
//判断是否是get类型的
if (!request.getMethod().equalsIgnoreCase("get")) {
return method.invoke(request, args);
}
//执行到这里,只能是get类型的getParameter方法了。
String value = (String) method.invoke(request, args);
if (value == null) {
return null;
}
return new String(value.getBytes("ISO8859-1"), "UTF-8");
}
}), response);
}
要实现动态代理必须要有接口,动态代理是基于接口来代理(实现接口的所有方法),如果没有接口的话,我们可以考虑cglib代理
cglib代理也叫做子类代理,从内存中创建出一个子类来拓展目标对象的功能
总的来说:代理模式是我们写代码中用得很多的一种模式了,Spring的AOP底层其实就是动态代理来实现的–>面向切面编程
其实只要记住一点:原有的对象需要额外的功能,想想动态代理这项技术!
来源:CSDN
作者:AlexNii
链接:https://blog.csdn.net/weixin_40920882/article/details/104515016