内省(IntroSpector)、反射及IntrospectorCleanupListener

7 篇文章 0 订阅

内省(IntroSpector)

     内省(IntroSpector)是Java语言对JavaBean 类属性、方法及事件的一种处理方法,只有符合JavaBean规则的类的成员才可以采用内省API进行操作.
     其操作方式是通过Introspector的getBeanInfo方法获取BeanInfo对象,再得到属性描述器PropertyDecriptor后再进行各种操作。

     PropertyDescriptor类表示JavaBean类通过存储器导出一个属性。主要方法:

1. getPropertyType(),获得属性的Class对象;
2. getReadMethod(),获得用于读取属性值的方法;
3. getWriteMethod(),获得用于写入属性值的方法;
4. hashCode(),获取对象的哈希值;
5. setReadMethod(Method readMethod),设置用于读取属性值的方法;
6. setWriteMethod(Method writeMethod),设置用于写入属性值的方法。

示例:

package com.example.springsource;

import java.beans.*;
import java.lang.reflect.Method;

/**
	1).addField属性没有对应的get/set方法,则不能进行操作.
	2).没有对应的missName属性,但是可以用getMissName()/setMissName方法,推测是去掉set前缀,然后取剩余部分.

 * @author Taxz
 * @version 1.0.0
 * @ClassName IntrospectorExample.java
 * @Description TODO
 * @createTime 2020年06月16日 17:15:00
 */
public class IntrospectorExample {

    public static void main (String[] args) throws Exception {

        //获取保存Foo.class的属性,方法和事件的BeanInfo
        BeanInfo beanInfo = Introspector.getBeanInfo(Foo.class);

        Foo foo = new Foo();
        foo.setName("foo");
        foo.setGrade(1);
        foo.setDetail("info....");
        System.out.println("The foo created : " + foo);

        BeanDescriptor bd = beanInfo.getBeanDescriptor();
        System.out.println("Bean name: " + bd.getName());
        System.out.println("Bean class: " + bd.getBeanClass());
        //属性描述器
        for (PropertyDescriptor pd : beanInfo.getPropertyDescriptors()) {
            System.out.println("----------");
            System.out.println("属性name: " + pd.getName());
            System.out.println("属性type: " + pd.getPropertyType());

            if (pd.getPropertyType().isAssignableFrom(java.lang.String.class)) {
                System.out.println("通过getReadMethod()方法获取value: " + pd.getReadMethod().invoke(foo));
                pd.getWriteMethod().invoke(foo, pd.getName()+"2");
                System.out.println("获取getWriteMethod()设置后的value: " + pd.getReadMethod().invoke(foo));
            }
            if (pd.getPropertyType().isAssignableFrom(java.lang.Integer.class)) {
                System.out.println("通过getReadMethod()方法获取value: " + pd.getReadMethod().invoke(foo));
                Integer value = (Integer) pd.getReadMethod().invoke(foo);
                pd.getWriteMethod().invoke(foo, value+1);
                System.out.println("获取getWriteMethod()设置后的value: " + pd.getReadMethod().invoke(foo));
            }

        }

    }

   public static class Foo {
        private String name;
        private Integer  grade;
        private String detail;
        private String addField;


        public String getMissName() {
            return "getMissName";
        }

        public void setMissName(String missName) {
            System.out.println(missName);
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public Integer getGrade() {
            return grade;
        }

        public void setGrade(Integer grade) {
            this.grade = grade;
        }

        public String getDetail() {
            return detail;
        }

        public void setDetail(String detail) {
            this.detail = detail;
        }
    }
}
//--------------------执行结果
The foo created : com.example.springsource.IntrospectorExample$Foo@5d3411d
Bean name: IntrospectorExample$Foo
Bean class: class com.example.springsource.IntrospectorExample$Foo
----------
属性name: class
属性type: class java.lang.Class
----------
属性name: detail
属性type: class java.lang.String
通过getReadMethod()方法获取value: info....
获取getWriteMethod()设置后的value: detail2
----------
属性name: grade
属性type: class java.lang.Integer
通过getReadMethod()方法获取value: 1
获取getWriteMethod()设置后的value: 2
----------
属性name: missName
属性type: class java.lang.String
通过getReadMethod()方法获取value: getMissName
missName2
获取getWriteMethod()设置后的value: getMissName
----------
属性name: name
属性type: class java.lang.String
通过getReadMethod()方法获取value: foo
获取getWriteMethod()设置后的value: name2
反射(Reflect)

     JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
     简单点说: 反射就是可以通过全类名来得到对象(类,属性,方法)的技术。例如我们可以通过类名来生成一个类的实例;可以获取方法名,调用这个方法;也可以获取属性名访问这个属性的值,示例可自行查看文档.

IntrospectorCleanupListener

在web.xml配置,

<!-- 解决java.beans.Introspector导致的内存泄漏的问题(必须放在listener第1个位置) -->
<listener>
   <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
</listener>
作用解释

     JDK中的java.beans.Introspector类的用途是发现Java类是否符合JavaBean规范, 如果有的框架或程序用到了Introspector类,那么就会启用一个系统级别的缓存,此缓存会存放一些曾加载并分析过的JavaBean的引用。当Web服务器关闭时,由于此缓存中存放着这些JavaBean的引用,所以垃圾回收器无法回收Web容器中的JavaBean对象,最后导致内存变大。而org.springframework.web.util.IntrospectorCleanupListener就是专门用来处理Introspector内存泄漏问题的辅助类。IntrospectorCleanupListener会在
     Web服务器停止时清理Introspector缓存,使那些Javabean能被垃圾回收器正确回收。Spring自身不会出现这种问题,因为Spring在加载并分析完一个类之后会马上刷新JavaBeans Introspector缓存,这就保证Spring中不会出现这种内存泄漏的问题。但有些程序和框架在使用了JavaBeans Introspector之后,没有进行清理工作(如 Quartz,Struts),最后导致内存泄漏.

      有不足之处欢迎指正!

参考文献

https://www.cnblogs.com/qiankun-site/p/5886673.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值