• Java动态生成类以及动态添加属性


    有个技术实现需求:动态生成类,其中类中的属性来自参数对象中的全部属性以及来自参数对象properties文件。

    那么技术实现支持:使用CGLib代理。

    具体的实现步骤:

    1.配置Maven文件:

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.journey</groupId>
        <artifactId>journey</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <dependencies>
            <dependency>
                <groupId>cglib</groupId>
                <artifactId>cglib</artifactId>
                <version>2.2.2</version>
            </dependency>
        </dependencies>
    
    </project>

    2.封装的cglib类

    package com.journey;
    
    import net.sf.cglib.beans.BeanGenerator;
    import net.sf.cglib.beans.BeanMap;
    
    import java.util.Iterator;
    import java.util.Map;
    import java.util.Set;
    
    /**
     * Created by little_eleventh_wolf on 2017/11/18.
     */
    public class DynamicBean {
        private Object object = null; //动态生成的类
        private BeanMap beanMap = null; //存放属性名称以及属性的类型
    
        public DynamicBean() {
            super();
        }
    
        public DynamicBean(Map propertyMap) {
            this.object = generateBean(propertyMap);
            this.beanMap = BeanMap.create(this.object);
        }
    
        /**
         * @param propertyMap
         * @return
         */
        private Object generateBean(Map propertyMap) {
            BeanGenerator generator = new BeanGenerator();
            Set keySet = propertyMap.keySet();
            for(Iterator i = keySet.iterator(); i.hasNext(); ) {
                String key = (String) i.next();
                generator.addProperty(key, (Class) propertyMap.get(key));
            }
            return generator.create();
        }
    
        /**
         * 给bean属性赋值
         * @param property 属性名
         * @param value 值
         */
        public void setValue(Object property, Object value) {
            beanMap.put(property, value);
        }
    
        /**
         * 通过属性名得到属性值
         * @param property 属性名
         * @return 值
         */
        public Object getValue(String property) {
            return beanMap.get(property);
        }
    
        /**
         * 得到该实体bean对象
         * @return
         */
        public Object getObject() {
            return this.object;
        }
    }

    3.需求的实现类:

    package com.journey;
    
    import java.beans.BeanInfo;
    import java.beans.Introspector;
    import java.beans.PropertyDescriptor;
    import java.io.InputStream;
    import java.lang.reflect.Method;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Properties;
    import java.util.Set;
    
    /**
     * Created by little_eleventh_wolf on 2017/11/18.
     */
    public class ClassUtil {
        private String filePath = "/config/"; //配置文件路径
    
        public String getFilePath() {
            return filePath;
        }
    
        public void setFilePath(String filePath) {
            this.filePath = filePath;
        }
    
        public Object dynamicClass(Object object) throws Exception {
            HashMap returnMap = new HashMap();
            HashMap typeMap = new HashMap();
            //读取配置文件
            Properties prop = new Properties();
            String sourcepackage = object.getClass().getName();
            String classname = sourcepackage.substring(sourcepackage.lastIndexOf(".") + 1);
            InputStream in = ClassUtil.class.getResourceAsStream(filePath + classname + ".properties");
            prop.load(in);
    
            Set<String> keylist = prop.stringPropertyNames();
    
            Class type = object.getClass();
            BeanInfo beanInfo = Introspector.getBeanInfo(type);
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for(int i = 0; i < propertyDescriptors.length; i++) {
                PropertyDescriptor descriptor = propertyDescriptors[i];
                String propertyName = descriptor.getName();
                if(!propertyName.equals("class")) {
                    Method readMethod = descriptor.getReadMethod();
                    Object result = readMethod.invoke(object, new Object[0]);
                    if(result != null) {
                        returnMap.put(propertyName, result);
                    } else {
                        returnMap.put(propertyName, "");
                    }
                    typeMap.put(propertyName, descriptor.getPropertyType());
                }
            }
            //加载配置文件中的属性
            Iterator<String> iterator = keylist.iterator();
            while(iterator.hasNext()) {
                String key = iterator.next();
                returnMap.put(key, prop.getProperty(key));
                typeMap.put(key, Class.forName("java.lang.String"));
            }
            //map转换成实体对象
            DynamicBean bean = new DynamicBean(typeMap);
            //赋值
            Set keys = typeMap.keySet();
            for(Iterator it = keys.iterator(); it.hasNext(); ) {
                String key = (String) it.next();
                bean.setValue(key, returnMap.get(key));
            }
            Object obj = bean.getObject();
            return obj;
        }
    
        public static void main(String[] args) throws Exception {
            new ClassUtil().dynamicClass(new LeapRole()/*LeapRole是个普通类,未贴源码*/);
        }
    }

    4.技术实现目的:前台框架表格数据源实际上就是带有数据的实体,但是grid中数据的类型、以及是否可见、toolbar工具栏上的按钮、是否分页,是针对实体而言,所以目前把这些信息作为实体的配置文件。在展示页面之前,读取全部信息,转为参数对象的完整对象

  • 相关阅读:
    STL 源代码分析 算法 stl_algo.h -- includes
    Objective-c 算术函数和常量代表
    文件比较,文件夹比较-- vimdiff,beyond compare, compare suite, WinMerge,Kdiff3
    PHP+lghttpd + postgresql 环境搭建
    开源免费跨平台opengl opencv webgl gtk blender, opengl贴图程序
    expect 参数处理之一
    几款屏幕录制软件 ActivePresente
    gcc -D 传值给代码,默认值为1
    error: /usr/include/stdio.h: Permission denied 的一种情况分析
    linux内核编译环境配置
  • 原文地址:https://www.cnblogs.com/firstdream/p/10078673.html
Copyright © 2020-2023  润新知