黑马程序员_Java高新技术(下)

-------    android培训java培训、期待与您交流! ----------

内省(IntroSpector

JavaBean

   JavaBean是一种特殊的Java类,主要用于传递数据信息,这种java类中的方法主要用于访问私有的字段,且方法名符合某种命名规则。
如果要在两个模块之间传递多个信息,可以将这些信息封装到一个JavaBean中,这种JavaBean的实例对象通常称之为值对象(Value Object,简称VO)。这些信息在类中用私有字段来存储,如果读取或设置这些字段的值,则需要通过一些相应的方法来访问,大家觉得这些方法的名称叫什么好呢?JavaBean的属性是根据其中的setter和getter方法来确定的,而不是根据其中的成员变量。如果方法名为setId,中文意思即为设置id,至于你把它存到哪个变量上,用管吗?如果方法名为getId,中文意思即为获取id,至于你从哪个变量上取,用管吗?去掉set前缀,剩余部分就是属性名,如果剩余部分的第二个字母是小写的,则把剩余部分的首字母改成小的。
  setId()的属性名-id
  isLast()的属性名-last
  setCPU的属性名是什么?-CPU
  getUPS的属性名是什么?-UPS

总之,一个类被当作javaBean使用时,JavaBean的属性是根据方法名推断出来的,它根本看不到java类内部的成员变量。

一个符合JavaBean特点的类可以当作普通类一样进行使用,但把它当JavaBean用肯定需要带来一些额外的好处,我们才会去了解和应用JavaBean!好处如下:
  在Java EE开发中,经常要使用到JavaBean。很多环境就要求按JavaBean方式进行操作,别人都这么用和要求这么做,那你就没什么挑选的余地!

JDK中提供了对JavaBean进行操作的一些API,这套API就称为内省。如果要你自己去通过getX方法来访问私有的x,怎么做,有一定难度吧?用内省这套api操作JavaBean比用普通类的方式更方便

采用遍历BeanInfo的所有属性方式来查找和设置某个RefectPoint对象的x属性。在程序中把一个类当作JavaBean来看,就是调用IntroSpector.getBeanInfo方法,得到的BeanInfo对象封装了把这个类当作JavaBean看的结果信息,得到BeanInfo最好采用“obj.getClass()”方式,而不要采用“类名.class”方式,这样程序更通用

public static void main(String[] args) throws Exception{
		// TODO Auto-generated method stub
		ReflectPoint pt1 = new ReflectPoint(3,5);
		Object retVal = getProperty(pt1);
		System.out.println(retVal);
		
		PropertyDescriptor pd2 = null;
		String propertyName = "y";
		Object value = 7;
		setProperty(pt1, propertyName, value);	
		
		//先通过调用普通java类的方法的方式获得结果,然后在这之前插入BeanUtil的get和set操作,见下面的代码
		//System.out.println(pt1.getY());
		
		System.out.println(BeanUtils.getProperty(pt1, "y"));
		BeanUtils.setProperty(pt1, "y", "99");

		System.out.println(pt1.getY());
		PropertyUtils.setProperty(pt1, "y", 999);
		System.out.println(PropertyUtils.getProperty(pt1, "y").getClass().getName());	
	}

	private static Object getProperty(ReflectPoint pt1) {
		Object retVal = null;
		PropertyDescriptor pd = null;
		try {
			pd = new PropertyDescriptor("y",pt1.getClass());
			retVal = pd.getReadMethod().invoke(pt1);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return retVal;
	}

	private static void setProperty(Object pt1, String propertyName,
			Object value) {
		/*PropertyDescriptor pd2;
		try {
			pd2 = new PropertyDescriptor(propertyName,pt1.getClass());
			pd2.getWriteMethod().invoke(pt1,value);
		} catch (Exception e) {
			e.printStackTrace();
		}*/
		
		try {
			BeanInfo beanInfo = Introspector.getBeanInfo(pt1.getClass());
			PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
			for(PropertyDescriptor pd :pds){
				if(pd.getName().equals(propertyName)){
					pd.getWriteMethod().invoke(pt1,value);
					break;
				}
			}
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IntrospectionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}


 代理

 为已存在的多个具有相同接口的目标类的各个方法增加一些系统功能,例如,异常处理、日志、计算方法的运行时间、事务管理、等等,你准备如何做?
 编写一个与目标类具有相同接口的代理类,代理类的每个方法调用目标类的相同方法,并在调用方法时加上系统功能的代码。

 如果采用工厂模式和配置文件的方式进行管理,则不需要修改客户端程序,在配置文件中配置是使用目标类、还是代理类,这样以后很容易切换,譬如,想要日志功能时就配置代理类,否则配置目标类,这样,增加系统功能很容易,以后运行一   段时间后,又想去掉系统功能也很容易

 

AOPAspectoriented program ,简称AOP)

   面向方面编程。系统中存在交叉业务,一个交叉业务就是要切入到系统中的一个方面,即为AOP。
 AOP的目标就是要使交叉业务模块化,可以采用将切面代码移动到原始方法的周围,这与直接在方法中编写切面代码的运行效果相同。
 代理技术可以很好的解决这种问题,是实现AOP功能的核心和关键技术。

动态代理技术:
     JVM可以在运行期动态生成出类的字节码,这种动态生成的类被用作代理类,即动态代理类。
     JVM生成的动态类必须实现一个或多个接口,所以JVM生成的动态类只能用作具有相同接口的目标类的代理。
     CGLIB库(目前开源,也许将来会加到jdk中)可以动态生成一个类的子类,一个类的子类也可以用作该类的代理,所以,如果要为一个没有实现接口的类生成动态代理类,那么可以使用CGLIB库。
     代理类的各个方法中通常除了要调用目标的相应方法和对外返回目标返回的结果外,还可以在代理方法中的如下四个位置加上系统功能代码。
     a.在调用目标方法之前
     b.在调用目标方法之前
     c.在调用目标方法前后
     d.在处理目标方法异常的catch块中

创建动态类的实例对象:
     首先用反射获得构造方法。
     编写一个最简单的invocationhandler类
     调用构造方法创建动态类的实例对象,并将编写的invocationhandler类的实例对象传进去。

JVM创建动态类所需信息:
     生成的类中有哪些方法,通过让其实现哪些接口的方式进行告知。
     产生的类的字节码必须有一个关联的类加载器对象。
     生成的类中的方法的代码,我们把代码写在一个约定好的接口对象的方法中,把对象传给他,它调用我们的方法,即插入了我们的代码。
     提供执行代码的对象就是那个invocationhandler对象,是在创建动态类的实例对象的构造方法时传进去的。
     也可以用Proxy.newinstance方法直接一步就创建出代理对象

动态代理工作原理图

用于为某个对象生成和返回其代理对象,源对象必须实现接口,生成的代理对象会实现与源对象相同的接口

注意:

源对象的类必须自己定义时就实现接口,从该类的祖辈类上继承的接口是无效的

该方法接口两个参数:一个是目标对象,另一个是封装了用户系统功能代码的Advice对象,该对象必须实现Advice接口

getProxy

由此联想到spring的一个问题:spring无法将通知应用到目标类的父类的方法上,例如,我们写的Action继承了DispatachAction,那么spring无法将advice应用到execute方法上。

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值