上一篇我们开发了一个简单的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就算开发完毕了。