xiejun
2024-11-01 80b6cbfc9c861469146318d0b3dd5f8b8b525b8a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package org.springblade.core.tool.beans;
 
import org.springframework.asm.ClassVisitor;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.cglib.core.AbstractClassGenerator;
import org.springframework.cglib.core.ReflectUtils;
 
import java.security.ProtectionDomain;
 
/**
 * 重写 cglib BeanMap,支持链式bean
 *
 * @author L.cm
 */
public abstract class BladeBeanMap extends BeanMap {
    protected BladeBeanMap() {
    }
 
    protected BladeBeanMap(Object bean) {
        super(bean);
    }
 
    public static BladeBeanMap create(Object bean) {
        BladeGenerator gen = new BladeGenerator();
        gen.setBean(bean);
        return gen.create();
    }
 
    /**
     * newInstance
     *
     * @param o Object
     * @return BladeBeanMap
     */
    @Override
    public abstract BladeBeanMap newInstance(Object o);
 
    public static class BladeGenerator extends AbstractClassGenerator {
        private static final Source SOURCE = new Source(BladeBeanMap.class.getName());
 
        private Object bean;
        private Class beanClass;
        private int require;
 
        public BladeGenerator() {
            super(SOURCE);
        }
 
        /**
         * Set the bean that the generated map should reflect. The bean may be swapped
         * out for another bean of the same type using {@link #setBean}.
         * Calling this method overrides any value previously set using {@link #setBeanClass}.
         * You must call either this method or {@link #setBeanClass} before {@link #create}.
         *
         * @param bean the initial bean
         */
        public void setBean(Object bean) {
            this.bean = bean;
            if (bean != null) {
                beanClass = bean.getClass();
            }
        }
 
        /**
         * Set the class of the bean that the generated map should support.
         * You must call either this method or {@link #setBeanClass} before {@link #create}.
         *
         * @param beanClass the class of the bean
         */
        public void setBeanClass(Class beanClass) {
            this.beanClass = beanClass;
        }
 
        /**
         * Limit the properties reflected by the generated map.
         *
         * @param require any combination of {@link #REQUIRE_GETTER} and
         *                {@link #REQUIRE_SETTER}; default is zero (any property allowed)
         */
        public void setRequire(int require) {
            this.require = require;
        }
 
        @Override
        protected ClassLoader getDefaultClassLoader() {
            return beanClass.getClassLoader();
        }
 
        @Override
        protected ProtectionDomain getProtectionDomain() {
            return ReflectUtils.getProtectionDomain(beanClass);
        }
 
        /**
         * Create a new instance of the <code>BeanMap</code>. An existing
         * generated class will be reused if possible.
         *
         * @return {BladeBeanMap}
         */
        public BladeBeanMap create() {
            if (beanClass == null) {
                throw new IllegalArgumentException("Class of bean unknown");
            }
            setNamePrefix(beanClass.getName());
            BladeBeanMapKey key = new BladeBeanMapKey(beanClass, require);
            return (BladeBeanMap) super.create(key);
        }
 
        @Override
        public void generateClass(ClassVisitor v) throws Exception {
            new BladeBeanMapEmitter(v, getClassName(), beanClass, require);
        }
 
        @Override
        protected Object firstInstance(Class type) {
            return ((BeanMap) ReflectUtils.newInstance(type)).newInstance(bean);
        }
 
        @Override
        protected Object nextInstance(Object instance) {
            return ((BeanMap) instance).newInstance(bean);
        }
    }
 
}