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