【从零写javaweb框架】(十)加载AOP框架

上一篇我们开发了一个简单的AOP框架【从零写javaweb框架】(九)开发AOP框架,现在需要在项目启动时自动加载AOP框架。

首先在之前写的BeanHelper类中添加一个setBean方法,用于将Bean实例放入BeanMap中:

    /**
     * 设置Bean实例
     */
    public static void setBean(Class<?> cls, Object obj){
        BEAN_MAP.put(cls, obj);
    }


然后在ClassHelper中添加两个方法,用于获取带有Aspect注解的所有类:

    /**
     * 获取应用包名下某父类(或接口)的所有子类(或实现类)
     */
    public static Set<Class<?>> getClassSetBySuper(Class<?> superClass){
        Set<Class<?>> classSet = new HashSet<Class<?>>();
        for (Class<?> cls : CLASS_SET){
            // 判断cls是否为superClass的子类或实现
            if (superClass.isAssignableFrom(cls)&&!superClass.equals(cls)){
                classSet.add(cls);
            }
        }
        return classSet;
    }

    /**
     * 获取应用包名下带有某注解的所有类
     */
    public static Set<Class<?>> getClassSetByAnnotation(Class<? extends Annotation> annotationClass){
        Set<Class<?>> classSet = new HashSet<Class<?>>();
        for (Class<?> cls : CLASS_SET){
            if (cls.isAnnotationPresent(annotationClass)){
                classSet.add(cls);
            }
        }
        return classSet;
    }


然后就是整个AopHelper的代码:

package org.smart4j.framework.helper;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.smart4j.framework.annotation.Aspect;
import org.smart4j.framework.proxy.AspectProxy;
import org.smart4j.framework.proxy.Proxy;
import org.smart4j.framework.proxy.ProxyManager;

import java.lang.annotation.Annotation;
import java.util.*;

/**
 * desc : Aop助手类
 * Created by Lon on 2018/2/7.
 */
public final class AopHelper {

    private static final Logger LOGGER = LoggerFactory.getLogger(AopHelper.class);

    /**
     * 通过静态代码块来初始化整个AOP框架
     */
    static {
        try {
            // 获取各个代理类与目标类的映射关系
            Map<Class<?>, Set<Class<?>>> proxyMap = createProxyMap();
            // 获取目标类(被代理的类)与代理对象之间的映射关系
            Map<Class<?>, List<Proxy>> targetMap = createTargetMap(proxyMap);
            for (Map.Entry<Class<?>, List<Proxy>> targetEntry : targetMap.entrySet()){
                Class<?> targetClass = targetEntry.getKey();
                List<Proxy> proxyList = targetEntry.getValue();
                // CGLib生成代理对象
                Object proxy = ProxyManager.createProxy(targetClass, proxyList);
                // 把原来的class对应的bean替换成刚生成的代理对象
                BeanHelper.setBean(targetClass, proxy);
            }
        } catch (Exception e){
            LOGGER.error("aop failure", e);
        }
    }

    /**
     * 获取Aspect注解中设置的注解类
     */
    private static Set<Class<?>> createTargetClassSet(Aspect aspect) throws Exception{
        Set<Class<?>> targetClassSet = new HashSet<Class<?>>();
        // 例如,如果aspect的value是注解Controller.class,那么返回的targetClassSet就会是所有的Controller类
        Class<? extends Annotation> annotation = aspect.value();
        if (annotation != null && !annotation.equals(Aspect.class)){
            targetClassSet.addAll(ClassHelper.getClassSetByAnnotation(annotation));
        }
        return targetClassSet;
    }

    /**
     * 一个代理类会对应多个目标类(被代理的类)。
     * 这个方法会返回各个代理类与目标类 的映射关系
     */
    private static Map<Class<?>, Set<Class<?>>> createProxyMap() throws Exception{
        Map<Class<?>, Set<Class<?>>> proxyMap = new HashMap<Class<?>, Set<Class<?>>>();
        // 获取所有继承AspectProxy类的代理类
        Set<Class<?>> proxyClassSet = ClassHelper.getClassSetBySuper(AspectProxy.class);
        // 遍历所有代理类
        for (Class<?> proxyClass : proxyClassSet){
            // 如果当前代理类有Aspect注解
            if (proxyClass.isAnnotationPresent(Aspect.class)){
                Aspect aspect = proxyClass.getAnnotation(Aspect.class);
                Set<Class<?>> targetClassSet = createTargetClassSet(aspect);
                proxyMap.put(proxyClass, targetClassSet);
            }
        }
        return proxyMap;
    }

    /**
     * 获取目标类(被代理的类)与代理对象之间的映射关系
     */
    private static Map<Class<?>, List<Proxy>> createTargetMap(Map<Class<?>, Set<Class<?>>> proxyMap) throws Exception{
        Map<Class<?>, List<Proxy>> targetMap = new HashMap<Class<?>, List<Proxy>>();
        for (Map.Entry<Class<?>, Set<Class<?>>> proxyEntry : proxyMap.entrySet()){
            Class<?> proxyClass = proxyEntry.getKey();
            Set<Class<?>> targetClassSet = proxyEntry.getValue();
            for (Class<?> targetClass : targetClassSet){
                Proxy proxy = (Proxy) proxyClass.newInstance();
                if (targetMap.containsKey(targetClass)){
                    targetMap.get(targetClass).add(proxy);
                } else {
                    List<Proxy> proxyList = new ArrayList<Proxy>();
                    proxyList.add(proxy);
                    targetMap.put(targetClass, proxyList);
                }
            }
        }
        return targetMap;
    }

}


最后就是将AopHelper添加到HelperLoader中进行初始化:

package org.smart4j.framework;

import org.smart4j.framework.helper.*;
import org.smart4j.framework.util.ClassUtil;

/**
 * desc : 加载相应的Helper类
 * Created by Lon on 2018/1/28.
 */
public final class HelperLoader {

    public static void init(){
        Class<?>[] classList = {
                ClassHelper.class,
                BeanHelper.class,
                AopHelper.class,
                IocHelper.class,
                ControllerHelper.class
        };
        for (Class<?> cls : classList){
            ClassUtil.loadClass(cls.getName(), true);
        }
    }

}

需要注意的是,AopHelper要在IocHelper之前加载,因为首先需要通过AopHelper获取代理对象,然后才能通过IocHelper进行依赖注入。那么,一个简单的AOP就算开发完毕了。







idle是Python自带的集成开发环境(IDE),提供了代码编辑、调试和运行等功能。下面是idle中文版的安装和使用教程: 安装idle中文版: 1. 首先,确保你已经安装了Python。可以从Python官网(www.python.org)下载最新版本的Python安装包,并按照指引完成安装。 2. 打开Python安装目录,找到Lib目录下的idlelib文件夹,里面包含了idle的相关文件。将其中的idle.py文件复制到一个你方便访问的目录,比如桌面。 使用idle中文版: 1. 双击打开之前复制到桌面的idle.py文件,即可启动idle中文版。 2. 在idle界面的编辑窗口中,可以输入并编辑Python代码。可以使用快捷键Ctrl+N创建新文件,Ctrl+O打开已有文件,Ctrl+S保存文件。 3. 在编辑窗口中编完代码后,可以按下F5键或者点击菜单栏的`Run`->`Run Module`来运行代码。运行结果会在Python Shell窗口中显示出来。 4. 在调试方面,可以使用菜单栏的`Debug`->`Debugger`来启动调试器。调试器提供了断点、逐行调试等功能,可以帮助我们找出代码中的问题。 5. 另外,在idle中文版中还提供了一些其它功能,比如自动缩进、代码补全、语法高亮等,可以提高编代码的效率。 6. 当完成代码编并调试好后,可以选择菜单栏的`File`->`Exit`来退出idle中文版。 总之,idle中文版是一款简单易用的Python集成开发环境,通过上述步骤的安装和使用,你可以轻松地编、调试和运行Python代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值