java 面向对象(四十三):反射(七)反射应用四:动态代理
2024-09-06 14:09:01
1.代理模式的原理:
使用一个代理将对象包装起来, 然后用该代理对象取代原始对象。任何对原始对象的调用都要通过代理。代理对象决定是否以及何时将方法调用转到原始对象上。
2.静态代理
2.1 举例:
实现Runnable接口的方法创建多线程。
Class MyThread implements Runnable{} //相当于被代理类
Class Thread implements Runnable{} //相当于代理类
main(){
MyThread t = new MyThread();
Thread thread = new Thread(t);
thread.start();//启动线程;调用线程的run()
}
2.2 静态代理的缺点:
① 代理类和目标对象的类都是在编译期间确定下来,不利于程序的扩展。
② 每一个代理类只能为一个接口服务,这样一来程序开发中必然产生过多的代理。
3.动态代理的特点:
动态代理是指客户通过代理类来调用其它对象的方法,并且是在程序运行时根据需要动态创建目标类的代理对
象。
4.动态代理的实现
4.1 需要解决的两个主要问题:
问题一:如何根据加载到内存中的被代理类,动态的创建一个代理类及其对象。
(通过Proxy.newProxyInstance()实现)
问题二:当通过代理类的对象调用方法a时,如何动态的去调用被代理类中的同名方法a。
(通过InvocationHandler接口的实现类及其方法invoke())
4.2 代码实现:
/**
*
* 动态代理的举例
*
* @author shkstart
* @create 2019 上午 10:18
*/ interface Human{ String getBelief(); void eat(String food); }
//被代理类
class SuperMan implements Human{ @Override
public String getBelief() {
return "I believe I can fly!";
} @Override
public void eat(String food) {
System.out.println("我喜欢吃" + food);
}
} class HumanUtil{ public void method1(){
System.out.println("====================通用方法一===================="); } public void method2(){
System.out.println("====================通用方法二====================");
} } class ProxyFactory{
//调用此方法,返回一个代理类的对象。解决问题一
public static Object getProxyInstance(Object obj){//obj:被代理类的对象
MyInvocationHandler handler = new MyInvocationHandler(); handler.bind(obj); return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),handler);
} } class MyInvocationHandler implements InvocationHandler{ private Object obj;//需要使用被代理类的对象进行赋值 public void bind(Object obj){
this.obj = obj;
} //当我们通过代理类的对象,调用方法a时,就会自动的调用如下的方法:invoke()
//将被代理类要执行的方法a的功能就声明在invoke()中
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { HumanUtil util = new HumanUtil();
util.method1(); //method:即为代理类对象调用的方法,此方法也就作为了被代理类对象要调用的方法
//obj:被代理类的对象
Object returnValue = method.invoke(obj,args); util.method2(); //上述方法的返回值就作为当前类中的invoke()的返回值。
return returnValue; }
} public class ProxyTest { public static void main(String[] args) {
SuperMan superMan = new SuperMan();
//proxyInstance:代理类的对象
Human proxyInstance = (Human) ProxyFactory.getProxyInstance(superMan);
//当通过代理类对象调用方法时,会自动的调用被代理类中同名的方法
String belief = proxyInstance.getBelief();
System.out.println(belief);
proxyInstance.eat("四川麻辣烫"); System.out.println("*****************************"); NikeClothFactory nikeClothFactory = new NikeClothFactory(); ClothFactory proxyClothFactory = (ClothFactory) ProxyFactory.getProxyInstance(nikeClothFactory); proxyClothFactory.produceCloth(); }
}
体会:反射的动态性。
最新文章
- 无废话ExtJs 入门教程十七[列表:GridPanel]
- Redhat5.8 环境下编译安装 Redis 并将其注册为系统服务
- Android Studio编译运行project报错:····· finished with non-zero exit value 1
- Centos 如何安装Django环境
- E-R图向关系模式的转换
- php QQ登录
- Equivalent Strings (字符串相等?)
- Java Web开发: Tomcat中部署项目的三种方法
- Nagios安装部署
- 开放源代码的设计层面框架Spring——day03
- Spark启动报错|java.io.FileNotFoundException: File does not exist: hdfs://hadoop101:9000/directory
- 003_crlf注入漏洞
- 同构体字符串(如果 s 中的字符可以被替换得到 t ,那么这两个字符串是同构的。 所有出现的字符都必须用另一个字符替换,同时保留字符的顺序。两个字符不能映射到同一个字符上,但字符可以映射自己本身。)
- Python之路,第十三篇:Python入门与基础13
- POJ3258--River Hopscotch(Binary Search similar to POJ2456)
- ASP.NET后台输出js脚本代码
- 【用jQuery来判断浏览器的类型】及【javascript获取用户ip地址】
- iOS7入门开发全系列教程新地址
- DRAM(动态)存储器
- linux命令创建和修改用户及密码