【代码笔记】Java——远程监控、反射、代理、内省机制
- 远程控制的基本原理
- 远程控制(RemoteControl)拥有控制端和被控端双方。 控制方通过请求,取得对远端的操作,实现远端的事件回放功能,同时,应该看得到远端桌面的画面。而被控方必须在建立ServerSocket之后进行对外来请求的鉴听。
/**
* 客户端发送事件
* @param e
*/
public void sendEvent(InputEvent e){
try {
SinglClient.getInstance().getOos().writeObject(e);
SinglClient.getInstance().getOos().flush();
} catch (IOException e1) {
e1.printStackTrace();
}
}/**
* 客户端图片接收
* @throws Exception
*/
public void readImage() throws Exception{
int length = SinglClient.getInstance().getOis().readInt();
byte[] bytes = new byte[length];
SinglClient.getInstance().getOis().readFully(bytes);
//转换为图片
ImageIcon image = new ImageIcon(bytes);
label.setIcon(image);
label.repaint();
}package com.edp.client; import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.InputEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException; import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel; /**
* 监控端的屏幕展示界面
* @author minGe_000
*
*/
public class ControlFrame extends JFrame{
private JLabel label;
public void initFrame() {
//建立和服务器的连接
SinglClient.getInstance().getConenction();
//得到屏幕大小
Dimension dimen = Toolkit.getDefaultToolkit().getScreenSize();
this.setSize(dimen);
this.setResizable(false);
this.setDefaultCloseOperation(3);
this.setLocationRelativeTo(null);
this.setUndecorated(true);
label = new JLabel();
this.add(label);
this.setVisible(true);
new Thread(){
public void run() {
try{
while(true){
readImage();
Thread.sleep(100);
}
}catch(Exception e){
e.printStackTrace();
}
};
}.start();
//给窗体添加相应的监听
MouseAdapter adapter = new MouseAdapter() {
public void mouseMoved(MouseEvent e) {
super.mouseMoved(e);
//发送对象
sendEvent(e);
}
@Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
//发送对象
sendEvent(e);
}
@Override
public void mouseReleased(MouseEvent e) {
super.mouseReleased(e);
//发送对象
sendEvent(e);
}
@Override
public void mousePressed(MouseEvent e) {
super.mousePressed(e);
//发送对象
sendEvent(e);
}
@Override
public void mouseDragged(MouseEvent e) {
super.mouseDragged(e);
//发送对象
sendEvent(e);
}
};
this.addMouseListener(adapter);
this.addMouseMotionListener(adapter);
this.addMouseWheelListener(adapter);
//给窗体添加键盘监听
KeyAdapter key = new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
super.keyPressed(e);
//发送对象
sendEvent(e);
}
@Override
public void keyReleased(KeyEvent e) {
super.keyReleased(e);
//发送对象
sendEvent(e);
}
};
this.addKeyListener(key);
}
/**
* 客户端发送事件
* @param e
*/
public void sendEvent(InputEvent e){
try {
SinglClient.getInstance().getOos().writeObject(e);
SinglClient.getInstance().getOos().flush();
} catch (IOException e1) {
e1.printStackTrace();
}
}
/**
* 客户端图片接收
* @throws Exception
*/
public void readImage() throws Exception{
int length = SinglClient.getInstance().getOis().readInt();
byte[] bytes = new byte[length];
SinglClient.getInstance().getOis().readFully(bytes);
//转换为图片
ImageIcon image = new ImageIcon(bytes);
label.setIcon(image);
label.repaint();
}
}- 反射机制
Person类——用于定义Person对象的属性和方法
Car类——用于定义Car对象的属性和方法
Class类——用于定义类对象的属性方法
- 得到Class三种方法:
第一种方式:Object类中的getClass方法
第二种方式:类.class
第三种方式:通过Class类的forName方法获取
public Constructor<T> getConstructor(Class<?>... parameterTypes)
得到制定的公有(public)的类
public Constructor<?>[] getConstructors()
得到所有的公有(public)的类
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
得到所有的一个指定类
public Constructor<?>[] getDeclaredConstructors() 得到所有的类
package Reflect; /** * 通过一个对象获得完整的包名和类名 * */ class Demo{
} class hello{ public static void main(String[] args) { Demo demo=new Demo(); System.out.println(demo.getClass().getName()); } }运行结果:Reflect.Demo
package Reflect; class Person{ public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString(){ return "["+this.name+" "+this.age+"]"; } private String name; private int age; } class hello{ public static void main(String[] args) { Class<?> demo=null; try{ demo=Class.forName("Reflect.Person"); }catch (Exception e) { e.printStackTrace(); } Person per=null; try { per=(Person)demo.newInstance(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } per.setName("Rollen"); per.setAge(20); System.out.println(per); } }
运行结果:
Rollen 20
- 获得普通方法:
public Method getMethod(String name,Class<?>... parameterTypes)
public Method[] getMethods()
public Method getDeclaredMethod(String name,Class<?>... parameterTypes)
public Method[] getDeclaredMethods()
获取属性的方法:
public Field getField(String name)
public Field[] getFields()
public Field getDeclaredField(String name)
public Field[] getDeclaredFields()
- 获取类信息其他方法
public int getModifiers()
public Annotation[] getAnnotations()
public ClassLoader getClassLoader()
public Class<?>[] getInterfaces()
public String getName()
public boolean isAnnotation()
public boolean isEnum()
public boolean isInterface()
- 代理(Proxy):为其他对象提供一种代理以控制对这个对象的访问
我们书写执行一个功能的函数时,经常需要在其中写入与功能不是直接相关但很有必要的代 码,如日志记录,信息发送,安全和事务支持等,这些枝节性代码虽然是必要的,但它会带 来以下麻烦:
- 枝节性代码游离在功能性代码之外,它下是函数的目的,这是对OO是一种破坏
- 枝节性代码会造成功能性代码对其它类的依赖,加深类之间的耦合,而这是OO系统所竭 力避免的
- 枝节性代码带来的耦合度会造成功能性代码移植困难,可重用性降低
- 从法理上说,枝节性代码应该`监视'着功能性代码,然后采取行动,而不是功能性代码 `通知'枝节性代码采取行动,这好比吟游诗人应该是主动记录骑士的功绩而不是骑士主 动要求诗人记录自己的功绩
- 常见的代理
毫无疑问,枝节性代码和功能性代码需要分开来才能降低耦合程度,符合现代OO系统的要 求,我们可以使用代理模式完成这个要求。
代理模式的作用是:为其它对象提供一种代理以控制对这个对象的访问。在某些情况下,一 个客户不想直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介作用。 代理模式一般涉及到三个角色:
- 抽象角色:声明真实对象和代理对象的共同接口
- 代理角色:代理对象内部包含有真实角色的引用,从而可以操作真实角色,同时代理对象 与真实对象有相同的接口,能在任何时候代替真实对象,同时代理对象可以在执行真实对 象前后加入特定的逻辑以实现功能的扩展。
- 真实角色:代理角色所代表的真实对象,是我们最终要引用的对象
常见的代理有:
- 远程代理(Remote Proxy):对一个位于不同的地址空间对象提供一个局域代表对象,如RMI中的stub
- 虚拟代理(Virtual Proxy):根据需要将一个资源消耗很大或者比较复杂的对象,延迟加 载,在真正需要的时候才创建
- 保护代理(Protect or Access Proxy):控制对一个对象的访问权限。
- 智能引用(Smart Reference Proxy):提供比目标对象额外的服务和功能。
通过代理类这一中间层,能够有效控制对实际委托类对象的直接访问,也可以很好地隐藏和 保护实际对象,实施不同的控制策略,从而在设计上获得了更大的灵活性。
- 动态代理:
- Dynamic Prox
动态代理相比于静态代理,更具有灵活性
动态代理不用显式地让它实现与真实主题类(RealSubject)相同的接口(interface),而是把这种实现推迟到运行时。
- 所谓Dynamic Proxy是这样一种class:它是在运行时生成的class,在生成它时你必须提供一 组interface给它,然后该class就宣称它实现了这些 interface。你当然可以把该class的实 例当作这些interface中的任何一个来用。当然啦,这个Dynamic Proxy其实就是一个Proxy, 它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工 作。
- 动态代理关联的API
java.lang.reflect包下的类:
InvocationHandler类:invoke(Object obj,Method method,Object[] objs)
Proxy类:newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
一个典型的动态代理创建对象过程可分为以下三个步骤:
1、通过实现InvocationHandler接口创建自己的调用处理器 InvocationHandler handler = new InvocationHandlerImpl(被代理对象);
2、通过构造函数创建代理类实例,此时需将调用处理器对象作为参数被传入
Interface inter= (Interface)newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
3、通过Interface对象执行指定事物
inter.method();
- 代理模式与装饰者模式的区别
代理模式和装饰者模式很像,在典型的例子上,如spring的AOP、远程代理类、JDK的proxy, 都是代理模式。JDK里的输入/输出器是很典型的装饰器模式!但在有些场景上,对设计模式 入门的新手,还是有点难区分,UML类图基本没区别,都是实现同一个接口,一个类包装另一 个类。 两者的定义:
- 装饰器模式:能动态的新增或组合对象的行为
- 代理模式:为其他对象提供一种代理以控制对这个对象的访问
装饰模式是“新增行为”,而代理模式是“控制访问”。关键就是我们如何判断是“新增行 为”还是“控制访问”。你在一个地方写装饰,大家就知道这是在增加功能,你写代理,大 家就知道是在限制。
代理模式:在不改变接口的前提下,控制对象的访问
例子:孙悟空扮演并代替高家三小姐
孙悟空扮演高家三小姐,所以可以说孙悟空与高家三小姐具有共同的接口。如果猪八戒只想 见见高家三小姐的娇好面容,或者谈谈天说说地,那么高家三小姐的“代理”孙悟空是允许 的,但猪八戒想亲亲嘴,那么是不行的。这是保护代理模式的应用。只有代理对象认为合适 时,才会将客户端的请求传递给真实主题对象。
装饰模式:在不改变接口的前提下,动态扩展对象的功能
孙悟空有七十二般变化,在二郎神眼里,他永远是那只猢狲。装饰模式以对客户透明的方式 动态地给一个对象附加上更多的责任。换言之,客户端并不会觉得对象在装饰前和装饰后有 什么不同。装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。他的每 一种变化都给他带来一种附加的本领。他变成鱼儿时,就可以到水里游泳;他变成雀儿时, 就可以在天上飞行。而不管悟空怎么变化,在二郎神眼里,他永远是那只猢狲。装饰模式以 对客户透明的方式动态地给一个对象附加上更多的责任。换言之,客户端并不会觉得对象在 装饰前和装饰后有什么不同。装饰模式可以在不使用创造更多子类的情况下,将对象的功能 加以扩展。
- 内省机制
- Ø定义:1.是java语言对Bean类属性、事件的一种缺省(=默认)的处理机制
2.通过反射的方式操作JavaBean的属性
例如Student类中有name属性,则可以通过反射机制调用getName和setName方法设置新值
Ø补充:通过getName和setName方法访问name属性,这就是默认的规则,java的API中有提供访问bean的get和set
方法的接口,都存于java.bean包下面
- 实现内省三步走
1. Introspector的静态方法getBeanInfo,获取BeanInfo对象信息
2. 通过BeanInfo对象调用getPropertyDescriptors获取PropertyDescriptor(bean的所有属性描述)
3. 调用getWriteMethod和getReadMethod获取当前属性的get和set机制函数
技术归纳:
properties文件
java.util.Properties类
类名.class.getResourceAsStream("文件路径");
相关函数:
load函数:加载properties文件
getProperty函数:获取properties文件字段属性
- 一般的做法是通过类 Introspector 来获取某个对象的 BeanInfo 信息,然后通过 BeanInfo 来获取属性的描述器( PropertyDescriptor ),通过这个属性描述器就可以获取某个属性对应的 getter/setter 方法,然后我们就可以通过反射机制来调用这些方法。
/**
* 内省演示例子: 把某个对象的所有属性名称和值都打印出来
*/
public class IntrospectorDemo {
String name;
String height;
public static void main(String[] args) throws Exception{
IntrospectorDemo demo = new IntrospectorDemo();
demo.setName( "Winter Lau" );
demo.setHeight(null);
// 如果不想把父类的属性也列出来的话,
// 那 getBeanInfo 的第二个参数填写父类的信息
BeanInfo bi = Introspector.getBeanInfo(demo.getClass(), Object. class );
PropertyDescriptor[] props = bi.getPropertyDescriptors();
for ( int i=0;i<props.length;i++){
System.out.println(props[i].getName()+ "=" +
props[i].getReadMethod().invoke(demo, null ));
}
}
public String getName() {
return name;
}
public void setName(String name) {
this .name = name;
}
public String getHeight() {
return height;
}
public void setHeight(String height) {
this.height = height;
}
}Web开发框架Struts中的FormBean就是通过内省机制来将表单中的数据映射到类的属性上,因此要求FormBean的每个属性要有getter/setter方法。但也并不总是这样,什么意思呢?就是说对一个Bean类来讲,我可以没有属性,但是只要有getter/setter方法中的其中一个,那么Java的内省机制就会认为存在一个属性,比如类中有方法setMobile,那么就认为存在一个mobile的属性,这样可以方便我们把Bean类通过一个接口来定义而不用去关心具体实现,不用去关心 Bean中数据的存储。比如我们可以把所有的getter/setter方法放到接口里定义,但是真正数据的存取则是在具体类中去实现,这样可提高系统的扩展性。
总结:
将 Java 的反射以及内省应用到程序设计中去可以大大的提供程序的智能化和可扩展性。有很多项目都是采取这两种技术来实现其核心功能,例如我们前面提到的 Struts ,还有用于处理 XML 文件的 Digester 项目,其实应该说几乎所有的项目都或多或少的采用这两种技术。在实际应用过程中二者要相互结合方能发挥真正的智能化以及高度可扩展性。
【代码笔记】Java——远程监控、反射、代理、内省机制的更多相关文章
- day27(反射之内省机制)
内省 内省:底层是使用反射机制实现的,是对于反射的进一步封装. 反射:通过类名来获取类中的所有属性和方法及类中的所有隐藏的方法. 内省:通过一个标准类(javabean类)来获取bean中的字段.ge ...
- day27(反射之内省机制实现BeanUtils)
使用内省方式来实现beanUtils往对象里面存值 public class BeanInfoUtil2 { public static void setPropertyByIntrospector( ...
- Tomcat java zabbix 监控
排除汤姆猫错误的步骤 ps-ef | grep java或jps –lvm 查看java pid进程 netstat –lntup | grep java 查看java 端口有没有启动 查看 tomc ...
- 杨晓峰-Java核心技术-6 动态代理 反射 MD
目录 第6讲 | 动态代理是基于什么原理? 典型回答 考点分析 知识扩展 反射机制及其演进 动态代理 精选留言 Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAnd ...
- Java系列笔记(4) - JVM监控与调优【转】
Java系列笔记(4) - JVM监控与调优[转] 目录 参数设置收集器搭配启动内存分配监控工具和方法调优方法调优实例 光说不练假把式,学习Java GC机制的目的是为了实用,也就是为了在 ...
- Java 反射和内省实现spring的IOC和DI
1.构造两个JavaBean package com.spring.model; public class People { private Car car; public Car getCar() ...
- Java 基础【18】 反射与内省
1.概念定义 Java 反射机制(Reflect)容许程序在运行时加载.探知.使用编译期间完全未知的 class,核心类 java.lang.Class. 通过把指定类中各种元素映射成 java.la ...
- 理解Java的反射与内省及其区别
java的内省机制和反射机制什么区别 内省操作只针对JavaBean,只有符合JavaBean规则的类的成员才可以采用内省API进行操作....而反射则不同,一个类的所有成员都可以进行反射操作. 内省 ...
- 【Java基础】java中的反射机制与动态代理
一.java中的反射机制 java反射的官方定义:在运行状态下,可以获取任意一个类的所有属性和方法,并且可通过某类任意一对象实例调用该类的所有方法.这种动态获取类的信息及动态调用类中方法的功能称为ja ...
随机推荐
- P2053 [SCOI2007]修车 费用流
$ \color{#0066ff}{ 题目描述 }$ 同一时刻有N位车主带着他们的爱车来到了汽车维修中心.维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的.现在需要安排这M ...
- LINUX下PHP安装VLD扩展并测试OK
首先下载安装vld压缩包,下载前一定注意区分压缩包版本和php版本是否匹配,否则很可能后面make install 失败. //下载安装包—暂时以14版本为例 wget http://pecl.php ...
- UML类图和时序图符号
看懂UML类图和时序图 https://www.cnblogs.com/me115/p/4092632.html 内容目录: 从一个示例开始 类之间的关系 时序图 附录:<图说设计模式> ...
- mysql数据库怎么使用,mysql的使用方法
https://jingyan.baidu.com/article/5d368d1ec069c13f61c05742.html 数据库的开启与关闭: https://blog.csdn.net/u01 ...
- POJ 2182 Lost Cows (求序列第k大)
题解 二分+树状数组 显然最和一个数的值就是rank 那么其它数有什么规律? 从后往前匹配rank,我们可以发现第i个数的rank为还没有匹配的rank第(a[i]+1)大的数 这可以用 树状数组+二 ...
- dotnet体系结构
一.C#与.NET的关系 1.粗略地説,.net是一种在Windows平台上的编程架构————一种API. 2.C#编译器专门用于.net,这表示用C#编写的所有代码总是使用.NET Framewor ...
- Qt随笔 - QSettings
QSettings类提供了持久的跨平台应用程序设置. 嗯,一句话概括QSettings-- 创建 来看一下原型: QSettings::QSettings(const QString &org ...
- Jquery动态绑定事件处理函数 bind / on / delegate
1.bind方法绑定的事件处理函数不会应用到后来添加到DOM中的新元素.比如你在用bind给页面元素绑定事件之后,又新添加了一些与之前绑定过事件的元素一样的DOM元素,但是这些事件并不能在新的DOM元 ...
- 云服务的三种形式laas,paas,saas
“云”其实是互联网的一个隐喻,“云计算”其实就是使用互联网来接入存储或者运行在远程服务器端的应用,数据,或者服务. 云也是分层的 任何一个在互联网上提供其服务的公司都可以叫做云计算公司.其实云计算分几 ...
- linux 拓展之linux纯命令行界面变为图形界面
使用版本为6.x 1, 连接网络 没网络就下载不了哦 2,设置下yum源,我本机原来的yum源是网易的但是我用不了,我设置阿里云可以下载, 你们有这问题的可以试试 3, yum groupin ...