模拟spring注释版实现IOC,DI,IOP

1.需要处理的问题:如何扫描xml,如何根据包名获取包下的类,如何生成注释?

2.先建立一个核心类

public class SpringAnnotationFramework {
    private static List packages = new ArrayList<>();
    private static Map propertyDefinitions = new HashMap();
    private static List classes = new ArrayList<>();
    private static List configs = new ArrayList<>();
    private static Map singleton = new HashMap<>();

    public SpringAnnotationFramework(String fileName) {
        readXml(fileName);
        parsePackage();
    }

    /**
     * 读取xml文件
     *
     * @param fileName
     *            xml文件的路劲
     */
    private void readXml(String fileName) {
        SAXReader saxReader = new SAXReader();
        try {
            URL xmlUrl = this.getClass().getClassLoader().getResource(fileName);
            Document document = saxReader.read(xmlUrl);
            Map xMap = new HashMap<>();

            xMap.put("ns", "http://www.springframework.org/schema/beans");
            XPath xPath = document.createXPath("//ns:beans/ns:context_component-scan");
            xPath.setNamespaceURIs(xMap);
            List elements = xPath.selectNodes(document);
            for (Element element : elements) {
                String packgeName = element.attributeValue("base-package");
                Packages pack = new Packages();
                pack.setPackageName(packgeName);
                packages.add(pack);
            }

            // 获取properties文件的xml
            XPath uXPath = document.createXPath("//ns:beans/ns:util_properties");
            uXPath.setNamespaceURIs(xMap);
            List propElements = uXPath.selectNodes(document);
            for (Element element : propElements) {
                String pid = element.attributeValue("id");
                String location = element.attributeValue("location");
                PropertyDefinition pd = new PropertyDefinition();
                String fpath = location.split(":")[1];
                pd.initProp(fpath);
                propertyDefinitions.put(pid, pd);
            }

            // 解析aop中的xml
            XPath configXPath = document.createXPath("//ns:beans/ns:config");
            configXPath.setNamespaceURIs(xMap);
            List configElements = configXPath.selectNodes(document);
            for (Element element : configElements) {
                Config config = new Config();
                String flag = element.attributeValue("proxy-target-class");
                config.setProxy_target_class(flag);

                XPath aspectXPath = document.createXPath("ns:aspect");
                aspectXPath.setNamespaceURIs(xMap);
                List aspectElemnets = aspectXPath.selectNodes(element);
                for (Element aspectElement : aspectElemnets) {
                    Aspect aspect = new Aspect();
                    String id = aspectElement.attributeValue("id");
                    String ref = aspectElement.attributeValue("ref");
                    aspect.setId(id);
                    aspect.setRef(ref);
                    Object obj = singleton.get(ref);// 切面对象

                    XPath pointcutXPath = document.createXPath("ns:pointcut");
                    pointcutXPath.setNamespaceURIs(xMap);
                    List pointcutElements = pointcutXPath.selectNodes(aspectElement);
                    for (Element pointcutElement : pointcutElements) {
                        Pointcut pointcut = new Pointcut();
                        String pid = pointcutElement.attributeValue("id");
                        String expression = pointcutElement.attributeValue("expression");
                        pointcut.setId(pid);
                        pointcut.setExpression(expression);
                        aspect.getPonitCutMap().put(pid, pointcut);
                    }

                    XPath aroundXPath = document.createXPath("ns:around");
                    aroundXPath.setNamespaceURIs(xMap);
                    List aroundElements = aroundXPath.selectNodes(aspectElement);
                    for (Element aroundElement : aroundElements) {
                        Around around = new Around();
                        String pointcut_ref = aroundElement.attributeValue("pointcut-ref");
                        String method = aroundElement.attributeValue("method");
                        around.setPointcut_ref(pointcut_ref);
                        around.setMethod(method);
                        aspect.getAroundMap().put(pointcut_ref, around);
                    }
                    config.getAspectMap().put(id, aspect);
                    configs.add(config);
                }

            }

        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }

    /**
     * 根据xml得到包路径解析所有得类
     */
    private void parsePackage() {
        for (Packages p : packages) {
            String packageName = p.getPackageName();
            for (String name : packageName.split(",")) {
                String packagePath = name.replace(".", "/");
                packagePath = this.getClass().getClassLoader().getResource(packagePath).getFile();
                recurseFile(name, packagePath);
            }
        }
    }
    
    /**
     * 根据传过来的类路径,解析得到所有类储存在classes中
     *
     * @param fname
     *            包名
     * @param packagePath
     *            包路径
     */
    private void recurseFile(String fname, String packagePath) {
        File dir = new File(packagePath);
        if (!dir.exists() || !dir.isDirectory()) {
            return;
        }
        File[] files = dir.listFiles(new FileFilter() {

            @Override
            public boolean accept(File pathname) {
                return pathname.getName().endsWith(".class");
            }
        });
        for (File file : files) {
            if (file.isDirectory()) {
                recurseFile(fname + file.getName(), file.getAbsolutePath());
            }
            try {
                String filePath = file.getName().substring(0, file.getName().length() - 6);
                Class clazz = Class.forName(fname + "." + filePath);
                classes.add(clazz);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    }
    
    /**
     * 根据注解初始化所有类
     *
     * @param clz
     */
    public Object InstanceObject(String key) {
        for (Class clz : classes) {
            Annotation[] annotations = clz.getAnnotations();
            boolean flag = clz.isAnnotationPresent(Compnent.class);
            if (flag) {
                Compnent annotation = (Compnent) clz.getAnnotation(Compnent.class);
                String id = annotation.value();
                Object obj;
                try {
                    obj = clz.newInstance();
                    singleton.put(id, obj);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        // 实例化对象后,给对象中注入内容
        InjectionObject();
        //查看aop中是否有该类的切面,若有这将次返回值改成代理对象
        Object obj=decorateObject1(singleton.get(key));
        // 返回对象
        return obj;//返回值是obj
    }
    /**
     *
     */
    private Object decorateObject1(Object targetObject){
        String id = isAspectObject(targetObject);
        Object aspectObject = singleton.get(id);
        Object proxyObject=null;
        if(id!=null){
            JDKDynamicProxy proxy=new JDKDynamicProxy();
            proxyObject = proxy.getProxyObject(targetObject, aspectObject);
        }else{
            proxyObject=targetObject;
        }
        return proxyObject;
    }
    /**
     *
     * @param obj 判断该对象是否是要切入的目标对象
     * @return
     */
    private String isAspectObject(Object obj){
        String id=null;
        for(Config config:configs){
            for(Aspect aspect:config.getAspectMap().values()){
                for(Pointcut pointcut:aspect.getPonitCutMap().values()){
                    
                    String expression = pointcut.getExpression();
                    String method=expression.split(" ")[0];
                    String packageName=expression.split(" ")[1].split("[.][.]")[0];
                    String name = obj.getClass().getPackage().getName();
                    if(packageName.equals(name)){
                        id = pointcut.getId();
                    }
                }
            }
        }
        return id;
        
    }

    /**
     * 获取多利对象
     */
    private Object PrototypeInstanceObject(String key, Class clz) {
        Object obj = null;
        Annotation[] annotations = clz.getAnnotations();
        boolean flag = clz.isAnnotationPresent(Compnent.class);
        if (flag) {
            Compnent annotation = (Compnent) clz.getAnnotation(Compnent.class);
            String id = annotation.value();
            try {
                obj = clz.newInstance();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return obj;
    }

    /**
     * 初始化所有所有类后,将属性注入类中
     *
     * @param clz
     *            所有实例化得类
     */
    private void InjectionObject() {
        for (Object obj : singleton.values()) {
            Class clz = obj.getClass();
            Field[] fields = clz.getDeclaredFields();
            for (Field field : fields) {
                boolean flag = field.isAnnotationPresent(Resource.class);
                boolean valueFlag = field.isAnnotationPresent(Value.class);
                if (flag) {
                    Resource annotation = field.getAnnotation(Resource.class);
                    String name = annotation.name();
                    Object value = singleton.get(name);
                    String setMethodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
                    try {
                        Method method = clz.getMethod(setMethodName, field.getType());
                        method.invoke(obj, value);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                if (valueFlag) {
                    Value annotation = field.getAnnotation(Value.class);
                    String value = annotation.value();
                    if (value.contains("#")) {
                        String result = value.split("[{]")[1].split("[}]")[0];
                        String id = result.split("[.]")[0];
                        String key = result.split("[.]")[1];
                        PropertyDefinition propertyDefinition = propertyDefinitions.get(id);
                        String propValue = propertyDefinition.getProp(key);
                        try {
                            field.setAccessible(true);
                            field.set(obj, propValue);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }

    public Object doSingleton(String id) {
        return InstanceObject(id);
    }

    public Object doPrototype(String id, Class clz) {
        return PrototypeInstanceObject(id, clz);
    }

    public boolean isPrototype(Class clazz) {
        boolean flag = clazz.isAnnotationPresent(Prototype.class);
        return flag;
    }

    public Object getBean(String id) {
        return singleton.get(id);
    }

    public T getBean(String id, Class clazz) {
        Object obj;
        if (!isPrototype(clazz)) {
            obj = doSingleton(id);
        } else {
            obj = doPrototype(id, clazz);
        }
        return (T) obj;
    }
}

3.property类加载属性文件

public class PropertyDefinition {
    private Properties prop=new Properties();
    public void initProp(String classpath){
        String path = PropertyDefinition.class.getClassLoader().getResource(classpath).getPath();
        try {
            prop.load(new FileInputStream(path));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public String getProp(String key){
        return prop.getProperty(key);
    }

}

4.用于存放解析出来的类名

public class Packages {
    private String packageName;

    public String getPackageName() {
        return packageName;
    }

    public void setPackageName(String packageName) {
        this.packageName = packageName;
    }
    

}

5.用于处理aop(动态代理)

public class JDKDynamicProxy {
    
    public Object getProxyObject(final Object targetObject,final Object aspectObject){
        Object proxyObj=Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
                targetObject.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        ProceedingJoinPoint pjp=new ProceedingJoinPoint();
                        pjp.setTargetObject(targetObject);
                        pjp.setSignation(method);
                        pjp.setArgs(args);
                        Method[] methods = aspectObject.getClass().getDeclaredMethods();
                        Object result=null;
                        for (Method aspectMethod : methods) {
                            if("around".equals(aspectMethod.getName())){
                                result=aspectMethod.invoke(aspectObject, pjp);
                            }
                        }
                        return result;
                    }
                });
        return proxyObj;
    }
    
}

6动态代理的一部分

public class ProceedingJoinPoint {
    private Method signation;
    private Object targetObject;
    private Object[] args;
    
    public Object[] getArgs() {
        return args;
    }
    public void setArgs(Object[] args) {
        this.args = args;
    }
    public ProceedingJoinPoint() {
        super();
    }
    public ProceedingJoinPoint(Object targetObject) {
        this.targetObject = targetObject;
    }
    public Method getSignation() {
        return signation;
    }
    public void setSignation(Method signation) {
        this.signation = signation;
    }
    public Object getTargetObject() {
        return targetObject;
    }
    public void setTargetObject(Object targetObject) {
        this.targetObject = targetObject;
    }
    
    public Object proceed(){
        try {
            Object returnValue = signation.invoke(targetObject, args);
            return returnValue;
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            throw new RuntimeException();
        }
    }
    
}

7.用于存储around节点

public class Around {
    private String pointcut_ref;
    private String method;
    public String getPointcut_ref() {
        return pointcut_ref;
    }
    public void setPointcut_ref(String pointcut_ref) {
        this.pointcut_ref = pointcut_ref;
    }
    public String getMethod() {
        return method;
    }
    public void setMethod(String method) {
        this.method = method;
    }
    

}

8.annotation相关

1>Compnent

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Compnent {
    public String value();
    

}

2>Resource

@Target({ElementType.METHOD,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Resource {
    public String name() default "null";
    public String value() default "null";

}

3>Value

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Value {
    public String value() default "null";

}

4>Prototype

@Target(ElementType.TYPE)
public @interface Prototype {

}


你可能感兴趣的:(2017年3月)