黑马程序员:Java基础总结----静态代理模式&动态代理
来源:互联网 发布:java中方法的格式 编辑:程序博客网 时间:2024/05/18 03:50
黑马程序员:Java基础总结
静态代理模式&动态代理
ASP.Net+Android+IO开发、.Net培训、期待与您交流!
静态代理模式
public class Ts {
public static void main(String[] args) throws Exception {
// 通过中介公司生产一批衣服
ClothingProduct cp = new ProxCompany(new LiNingCompany());
cp.productClothing();
}
}
/**
* 定义生产一批衣服功能的接口
*
*/
interface ClothingProduct {
void productClothing(); // 有生产一批衣服的功能
}
/**
*
* 代理类:中介公司
*
*/
class ProxCompany implements ClothingProduct {
private ClothingProduct cp ; // 中介公司不会生产衣服,需要找一家真正能生产衣服的公司
ProxCompany(ClothingProduct cp) {
super();
this.cp = cp;
}
@Override
public void productClothing() {
System. out.println("收取1000块钱的中介费" );
cp.productClothing();
}
}
/**
*
* 李宁公司是生产服装的目标类
*
*/
class LiNingCompany implements ClothingProduct {
@Override
public void productClothing() {
System. out.println("生产一批衣服。。。。" );
}
}
上面程序的做法,使用的模式是静态代理模式
静态代理模式在现实编程中的弊端:
它的特征是代理类和目标对象的类都是在编译期间确定下来的,不利于程序上的扩展,上面示例中,如果客户还想找一个“生产一批鞋子”的工厂,那么还需要新增加一个代理类和一个目标类。如果客户还需要很多其他的服务,就必须一一的添加代理类和目标类。那就需要写很多的代理类和目标类
java.lang.reflect
类 Proxy
类 Proxy
Proxy
提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。
protected
Proxy(InvocationHandler h)
使用其调用处理程序的指定值从子类(通常为动态代理类)构建新的
Proxy
实例。protected InvocationHandler
h
此代理实例的调用处理程序。
static InvocationHandler
getInvocationHandler(Object proxy)
返回指定代理实例的调用处理程序。
static Class<?>
getProxyClass(ClassLoader loader, Class<?>... interfaces)
返回代理类的
java.lang.Class
对象,并向其提供类加载器和接口数组。static boolean
isProxyClass(Class<?> cl)
当且仅当指定的类通过
getProxyClass
方法或 newProxyInstance
方法动态生成为代理类时,返回 true。static Object
newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。
每个代理实例都具有一个关联的调用处理程序。对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的 invoke
方法。
public interface InvocationHandler 方法摘要
Object
invoke(Object proxy, Method method, Object[] args)
在代理实例上处理方法调用并返回结果。
- 参数:
proxy
- 在其上调用方法的代理实例method
- 对应于在代理实例上调用的接口方法的Method
实例。Method
对象的声明类将是在其中声明方法的接口,该接口可以是代理类赖以继承方法的代理接口的超接口。args
- 包含传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,则为null
。基本类型的参数被包装在适当基本包装器类(如java.lang.Integer
或java.lang.Boolean
)的实例中。- 返回:
- 从代理实例的方法调用返回的值。如果接口方法的声明返回类型是基本类型,则此方法返回的值一定是相应基本包装对象类的实例;否则,它一定是可分配到声明返回类型的类型。如果此方法返回的值为
null
并且接口方法的返回类型是基本类型,则代理实例上的方法调用将抛出NullPointerException
。否则,如果此方法返回的值与上述接口方法的声明返回类型不兼容,则代理实例上的方法调用将抛出ClassCastException
。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;
public class Ts {
public static void main(String[] args) throws Exception {
ArrayList test = new ArrayList();
// 代理只可以强转换成接口
Collection list = (Collection ) getProxy(test, new MyAdvice());
list.add(123);
list.add(123);
System. out.println(list);
}
public static Object getProxy(final Object target, final Advice adv)/* 终态是因为内部类调用 */ {
// 返回一个指定接口的代理类实例 obj
Object obj = Proxy. newProxyInstance(
// 定义代理类的类加载器
target.getClass().getClassLoader(),
// 代理类要实现的接口列表
target.getClass().getInterfaces(),
// 指派方法调用的调用处理程序 InvocationHandler
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
adv.begintime(method);
//target目标 ,args方法参数,调用原来的方法
Object retVal = method.invoke(target, args);
adv.endtime(method);
return retVal;
}
});
return obj;
}
}
//插入的建议接口
interface Advice {
void begintime(Method method);
void endtime(Method method);
}
//我的建议
class MyAdvice implements Advice {
@Override
public void begintime(Method method) {
Long time = System. currentTimeMillis();
System. out.println(method.getName() + time);
}
@Override
public void endtime(Method method) {
Long time = System. currentTimeMillis();
System. out.println(method.getName() + time);
}
}
一个更巧妙的方法:自定义一个处理程序
public class Ts {
public static void main(String[] args) throws Exception {
ProxyHandler handler= new ProxyHandler();
ClothingProduct cp2=(ClothingProduct)handler.newProxyInstance( new LiNingCompany());
cp2.productClothing();
}
}
class ProxyHandler implements InvocationHandler {
/* 目标对象 */
private Object target ;
/* 创建目标对象的代理对象 */
public Object newProxyInstance(Object target) {
this.target = target;
/*
* 第一个参数:定义代理类的类加载器
* 第二个参数:代理类要实现的接口 列表
* 第三个参数:指派方法调用的调用处理程序
*/
return Proxy.newProxyInstance(this. target.getClass().getClassLoader(),
this.target .getClass().getClasses(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result = null;
System. out.println("目标对象上的方法调用之前可以添加其他代码。。。" );
result = method.invoke( this.target , args); // 通过反射调用目标对象上的方法
System. out.println("目标对象上的方法调用之后可以添加其他代码。。。" );
return result;
}
}
ASP.Net+Android+IO开发、.Net培训、期待与您交流!
- 黑马程序员:Java基础总结----静态代理模式&动态代理
- <黑马程序员>代理模式总结-静态代理
- <黑马程序员>代理模式总结-动态代理
- 黑马程序员_动态代理和静态代理总结
- 黑马程序员--Java基础--15动态代理
- 黑马程序员---java基础加强---动态代理
- 黑马程序员-->Java基础加强-->动态代理
- 黑马程序员--静态代理和动态代理
- 黑马程序员--静态代理和动态代理
- Java代理模式 静态代理 动态代理
- Java基础--代理模式(静态、动态)
- 黑马程序员【代理模式与Java动态代理】
- 黑马程序员-----代理之动态代理总结*
- Java代理模式 静态代理,动态代理,Cglib代理
- 黑马程序员-代理模式总结
- Java基础:静态代理和动态代理
- 【java基础】静态代理 VS 动态代理
- 黑马程序员-java动态代理
- iOS6.0 xcode4.5 设置 横屏
- hdu3001 travelling
- javascript中的$、#
- 对当前软件行业的一点点感想
- Java基础知识_框架的概念以及用反射开发框架的原理
- 黑马程序员:Java基础总结----静态代理模式&动态代理
- 黑马程序员_JAVA基础上
- 文本框获得焦点,并且同时清空文本框内原有的文字。 如果文本框内已经有用户输入的内容了,那么就不应该进行清除文本款内容这个动作
- NYOJ-6174问题-57
- poj 3468 树状数组解法(解决区间更新,区间求和)
- [项目]交通灯管理系统
- 检验方法
- [Effective C++] 继承与面向对象设计
- setContentView(R.layout.activity_main) Error解决方法