从零开始写javaweb框架笔记20-使框架具备AOP特性-开发AOP框架
2017-06-27 19:05
507 查看
借鉴Spring AOP的风格,写一个基于切面注解的AOP框架,需了解前面的动态代理技术
通过
来设置该注解只能应用在类上。该注解中包含了一个名为value的属性,它是一个注解类,用了定义Controller这类注解。在使用切面之前,我们需要先搭建一个代理框架。
这个Proxy接口中包括了一个doRroxy方法,传入一个ProxyChain,用于执行“链式代理操作”。所谓链式代理,也就是说,可将多个代理通过一条链子串起来,一个个地去执行,执行顺序取决于添加到链式上的先后顺序。
下面是ProxyChain的代码:
在ProxyChain类中,我们定义了一系列的成员变量,包括targetClass(目标类),targetObject(目标对象),targetMethod(目标方法),methodProxy(方法代理),methodParams(方法参数),此外还包括了proxyList(代理列表),proxyIndex(代理索引),这些成员变量在构造中进行初始化,并提供了几个重要的获值方法。
需要注意的是MethodProxy这个类,它是CGLib开源项目为我们提供的一个方法代理对象在doProxyChain方法中被使用。
需要解释的是doProxyChain方法,在该方法中,我们通过proxyIndex来充当代理对象的计数器,若未达到proxyList的上限,则从proxyList中取出相应的Proxy对象,并调用其doProxy方法。在Proxy接口的实现中会提供相应的横切逻辑,并调用doProxyChain方法,随后将再次调用当前ProxyChain对象的doProxyChain方法,直到proxyIndex达到proxyList的上限为止,最后调用methodProxy的invokeSuper方法,执行目标对象的业务逻辑。
我们必须在pom.xml文件中添加CGLib的Maven依赖:
现在我们需要些一个类,让它提供一个创建代理对象的方法,输入一个目标类和一组Proxy接口实现,输出一个代理对象,将该类命名为ProxyManager,让它来创建所有的代理对象,代码如下:
使用CGLib提供的Enhance的create方法来创建代理对象,将intercept的参数传入ProxyChain的构造器中即可。
谁来调用ProxyManager呢,当然是切面类了,因为在切面类中,需要一个目标方法被调用前后增加相应的逻辑。我们有必要写一个抽象类,让它提供一个模板方法,并在该抽象类的具体实现中扩展相应的抽象方法。我们不妨将该抽象类命名为AspectProxy,代码如下:
需要注意的是AspectProxy类中的doProxy方法,我们从proxyChain参数中获取了目标类,目标方法与目标参数,随后通过一个try。。。catch。。。finally代码块来实现调用框架,从框架中抽象出一系列的“钩子方法”,这些抽象方法可在AspectProxy的子类中选择性地进行实现,就像下面这样:
我们只需实现before与after方法,就可以在目标方法执行前后添加其他需要执行的代码了。
那么这样就结束了吗?no,我们还需要在整个框架里使用ProxyManager来创建代理对象,并将该代理对象放入框架底层的Bean Map中,随后才能通过IOC将代理的对象注入到其他对象中。
在AopHelper中我们需要获取所有的目标类及其被拦截的切面类实例,并通过ProxyManager的createProxy方法来创建代理对象,最后将其放入Bean Map中。
首先需要为BeanHelper类添加一个setBean方法,用于将Bean实例放入Bean Map中,代码如下:
然后,由于我们需要扩展AspectProxy抽象类的所有具体类,此外,还需要获取带有Aspect注解的所有类,因此需要在ClassHelper中添加以下两个方法:
完整代码如下:
有了以上两个工具方法以后,我们就可以在AopHelper类中编写一个带有Aspect注解的所有类,把封装成一个方法:
获取Aspect注解中设置的注解类,若该注解类不是Aspect类,则可调用ClassHelper的getClassSetByAnnotation方法获取相关的类,并把这些类放入目标类集合中,最终返回这个集合。
紧接着我们需要获取代理类及其目标类集合之间的映射关系,一个代理类可对应一个或多个目标类。需要强调的是,这里所说的代理类指的是切面类。通过以下代码获取这个映射关系:
代理类需要扩展AspectProxy抽象类,还需要带有Aspect注解,只有满足这两个条件,才能根据Aspect注解中所定义的注解属性去获取该注解所对应的目标类集合,然后才能建立代理类与目标类集合之间的映射关系,最终返回这个映射关系
一旦获取了代理类与目标类集合之间的映射关系,就能根据这个关系分析出目标类与代理对象列表之间的映射关系,就像下面这样:
最后,在AopHelper中通过一个静态块来初始化整个AOP框架,代码如下:
获取代理类及其目标类集合的映射关系,进一步获取目标类与代理对象列表的映射关系,进而遍历这个映射关系,从中获取目标类与代理对象列表,调用ProxyManager.createProxy方法获取代理对象,调用BeanHelper.setBean方法,将该代理对象重新放入Bean Map中。
下面是AopHelper类的所有代码:
别忘了将AopHelper添加到HelperLoader中进行初始化,代码如下:
需要注意的是,AopHelper要在IocHelper之前加载,因为首先需要通过AopHelper获取代理对象,然后才能通过IocHelper进行依赖注入,到这里一个简单的AOP就开发完毕了。
github代码中的地址:https://github.com/wj903829182/smartframework
一:定义切面注解
在框架中添加一个名为Aspect的注解,代码如下:package org.smart4j.framework.annotation; import java.lang.annotation.*; /** * Created by jack on 2017/6/27. * 切面注解 */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface Aspect { /** * 注解 * @return */ Class<? extends Annotation> value(); }
通过
@Target(ElementType.TYPE)
来设置该注解只能应用在类上。该注解中包含了一个名为value的属性,它是一个注解类,用了定义Controller这类注解。在使用切面之前,我们需要先搭建一个代理框架。
二:搭建代理框架
在框架中添加一个名为Proxy的接口,代码如下:package org.smart4j.framework.proxy; /** * Created by jack on 2017/6/28. * 代理接口 */ public interface Proxy { Object doProxy(ProxyChain proxyChain) throws Throwable; }
这个Proxy接口中包括了一个doRroxy方法,传入一个ProxyChain,用于执行“链式代理操作”。所谓链式代理,也就是说,可将多个代理通过一条链子串起来,一个个地去执行,执行顺序取决于添加到链式上的先后顺序。
下面是ProxyChain的代码:
package org.smart4j.framework.proxy; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; /** * Created by jack on 2017/6/28. * 代理链 */ public class ProxyChain { private final Class<?> targetClass; private final Object targetObject; private final Method targetMethod; private final MethodProxy methodProxy; private final Object[] methodParams; private List<Proxy> proxyList = new ArrayList<Proxy>(); private int proxyIndex = 0; /** * 构造函数 * @param targetClass * @param targetObject * @param targetMethod * @param methodProxy * @param methodParams * @param proxyList */ public ProxyChain(Class<?> targetClass, Object targetObject, Method targetMethod, MethodProxy methodProxy, Object[] methodParams, List<Proxy> proxyList) { this.targetClass = targetClass; this.targetObject = targetObject; this.targetMethod = targetMethod; this.methodProxy = methodProxy; this.methodParams = methodParams; this.proxyList = proxyList; } public Object[] getMethodParams() { return methodParams; } public Class<?> getTargetClass() { return targetClass; } public Method getTargetMethod() { return targetMethod; } public Object doProxyChain()throws Throwable{ Object methodResult; if (proxyIndex < proxyList.size()){ methodResult = proxyList.get(proxyIndex++).doProxy(this); }else { methodResult = methodProxy.invokeSuper(targetObject,methodParams); } return methodResult; } }
在ProxyChain类中,我们定义了一系列的成员变量,包括targetClass(目标类),targetObject(目标对象),targetMethod(目标方法),methodProxy(方法代理),methodParams(方法参数),此外还包括了proxyList(代理列表),proxyIndex(代理索引),这些成员变量在构造中进行初始化,并提供了几个重要的获值方法。
需要注意的是MethodProxy这个类,它是CGLib开源项目为我们提供的一个方法代理对象在doProxyChain方法中被使用。
需要解释的是doProxyChain方法,在该方法中,我们通过proxyIndex来充当代理对象的计数器,若未达到proxyList的上限,则从proxyList中取出相应的Proxy对象,并调用其doProxy方法。在Proxy接口的实现中会提供相应的横切逻辑,并调用doProxyChain方法,随后将再次调用当前ProxyChain对象的doProxyChain方法,直到proxyIndex达到proxyList的上限为止,最后调用methodProxy的invokeSuper方法,执行目标对象的业务逻辑。
我们必须在pom.xml文件中添加CGLib的Maven依赖:
<!--添加cglib类库,实现动态代理--> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.2.2</version> </dependency>
现在我们需要些一个类,让它提供一个创建代理对象的方法,输入一个目标类和一组Proxy接口实现,输出一个代理对象,将该类命名为ProxyManager,让它来创建所有的代理对象,代码如下:
package org.smart4j.framework.proxy; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; import java.util.List; /** * Created by jack on 2017/6/28. * 代理管理器 */ public class ProxyManager { public static <T> T createProxy(final Class<T> targetClass, final List<Proxy> proxyList){ return (T) Enhancer.create(targetClass, new MethodInterceptor() { public Object intercept(Object targetObject, Method targetMethod, Object[] methodParams, MethodProxy methodProxy) throws Throwable { return new ProxyChain(targetClass,targetObject,targetMethod,methodProxy,methodParams,proxyList).doProxyChain(); } }); } }
使用CGLib提供的Enhance的create方法来创建代理对象,将intercept的参数传入ProxyChain的构造器中即可。
谁来调用ProxyManager呢,当然是切面类了,因为在切面类中,需要一个目标方法被调用前后增加相应的逻辑。我们有必要写一个抽象类,让它提供一个模板方法,并在该抽象类的具体实现中扩展相应的抽象方法。我们不妨将该抽象类命名为AspectProxy,代码如下:
package org.smart4j.framework.proxy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.lang.reflect.Method; /** * Created by jack on 2017/6/28. * 切面代理 */ public class AspectProxy implements Proxy{ private static final Logger LOGGER = LoggerFactory.getLogger(AspectProxy.class); public Object doProxy(ProxyChain proxyChain) throws Throwable { Object result = null; Class<?> cls = proxyChain.getTargetClass(); Method method = proxyChain.getTargetMethod(); Object [] params = proxyChain.getMethodParams(); begin(); try { if (intercept(cls,method,params)){ before(cls,method,params); result = proxyChain.doProxyChain(); after(cls,method,params); }else { result = proxyChain.doProxyChain(); } }catch (Exception e){ LOGGER.error("proxy failure ",e); error(cls,method,params); throw e; }finally { end(); } return result; } public boolean intercept(Class<?> cls,Method method,Object [] params) throws Throwable{ return true; } public void before(Class<?> cls,Method method,Object [] params) throws Throwable{ } public void after(Class<?> cls,Method method,Object [] params) throws Throwable{ } public void error(Class<?> cls,Method method,Object [] params) throws Throwable{ } public void begin(){} public void end(){} }
需要注意的是AspectProxy类中的doProxy方法,我们从proxyChain参数中获取了目标类,目标方法与目标参数,随后通过一个try。。。catch。。。finally代码块来实现调用框架,从框架中抽象出一系列的“钩子方法”,这些抽象方法可在AspectProxy的子类中选择性地进行实现,就像下面这样:
package org.smart4j.framework.aspect; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.smart4j.framework.annotation.Aspect; import org.smart4j.framework.annotation.Controller; import org.smart4j.framework.proxy.AspectProxy; import java.lang.reflect.Method; /** * Created by jack on 2017/7/17. */ @Aspect(Controller.class) public class ControllerAspect extends AspectProxy{ private static final Logger LOG = LoggerFactory.getLogger(ControllerAspect.class); private long begin; @Override public void before(Class<?> cls, Method method, Object[] params) throws Throwable { LOG.debug("------------begin--------------"); LOG.debug(String.format("class: %s",cls.getName())); LOG.debug(String.format("method: %s",method.getName())); begin = System.currentTimeMillis(); } @Override public void after(Class<?> cls, Method method, Object[] params) throws Throwable { LOG.debug(String.format("time: %s",System.currentTimeMillis()-begin)); LOG.debug("------------end--------------"); } }
我们只需实现before与after方法,就可以在目标方法执行前后添加其他需要执行的代码了。
那么这样就结束了吗?no,我们还需要在整个框架里使用ProxyManager来创建代理对象,并将该代理对象放入框架底层的Bean Map中,随后才能通过IOC将代理的对象注入到其他对象中。
三:加载AOP框架
按照之前的方式,为了加载AOP框架,我们需要编写一个名为AopHelper的类,然后将其添加到HelperLoader类中。在AopHelper中我们需要获取所有的目标类及其被拦截的切面类实例,并通过ProxyManager的createProxy方法来创建代理对象,最后将其放入Bean Map中。
首先需要为BeanHelper类添加一个setBean方法,用于将Bean实例放入Bean Map中,代码如下:
package org.smart4j.framework.helper; import org.smart4j.framework.util.ReflectionUtil; import java.util.HashMap; import java.util.Map; import java.util.Set; /** * Created by jack on 2017/5/23. * bean 助手类 */ public class BeanHelper { /** * 定义bean映射,(用于存放bean类与bean实例的映射关系) */ private static final Map<Class<?>,Object> BEAN_MAP = new HashMap<Class<?>, Object>(); /** * 静态代码块 */ static { Set<Class<?>> beanClassSet = ClassHelper.getBeanClassSet(); for (Class<?> beanClass : beanClassSet) { Object object = ReflectionUtil.newInstance(beanClass); BEAN_MAP.put(beanClass,object); } } /** * 获取Bean映射 */ public static Map<Class<?>,Object> getBeanMap(){ return BEAN_MAP; } /** * 获取Bean实例 */ public static <T> T getBean(Class<?> cls){ if (!BEAN_MAP.containsKey(cls)){ throw new RuntimeException("can not get bean by class:"+cls); } return (T) BEAN_MAP.get(cls); } /** * 设置Bean实例 * @param cls * @param obj */ public static void setBean(Class<?> cls,Object obj){ BEAN_MAP.put(cls,obj); } }
然后,由于我们需要扩展AspectProxy抽象类的所有具体类,此外,还需要获取带有Aspect注解的所有类,因此需要在ClassHelper中添加以下两个方法:
/** * 获取应用包名下某父类(或接口)的所有子类(或实现类) * @param superClass * @return */ public static Set<Class<?>> getClassSetBySupper(Class<?> superClass){ Set<Class<?>> classSet = new HashSet<Class<?>>(); for (Class<?> cls : CLASS_SET){ if (superClass.isAssignableFrom(cls) && !superClass.equals(cls)){ classSet.add(cls); } } return classSet; } /** * 获取应用包名带有某注解的所有类 * @param annotationClass * @return */ 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; }
完整代码如下:
package org.smart4j.framework.helper;
import org.smart4j.framework.annotation.Controller;
import org.smart4j.framework.annotation.Service;
import org.smart4j.framework.util.ClassUtil;
import java.lang.annotation.Annotation;
import java.util.HashSet;
import java.util.Set;
/**
* Created by jack on 2017/5/22.
* 类操作助手类
*/
public class ClassHelper {
/**
* 定义类集合,用于存放所加载的类
*/
private static final Set<Class<?>> CLASS_SET;
static {
String basePackage = ConfigHelper.getAppBasePackage();
CLASS_SET = ClassUtil.getClassSet(basePackage);
}
/**
* 获取应用包下的所有类
*/
public static Set<Class<?>> getClassSet() {
return CLASS_SET;
}
/**
* 获取应用包名下所有Service类
*/
public static Set<Class<?>> getServiceClassSet() {
Set<Class<?>> classSet = new HashSet<Class<?>>();
for (Class<?> cls : CLASS_SET) {
if (cls.isAnnotationPresent(Service.class)) {
classSet.add(cls);
}
}
return classSet;
}
/**
* 获取应用包名下所有Controller类
*/
public static Set<Class<?>> getControllerClassSet() {
Set<Class<?>> classSet = new HashSet<Class<?>>();
for (Class<?> cls : CLASS_SET) {
if (cls.isAnnotationPresent(Controller.class)) {
classSet.add(cls);
}
}
return classSet;
}
/**
* 获取应用包名下所有Bean类(包括Service,Controller)
*/
public static Set<Class<?>> getBeanClassSet() {
Set<Class<?>> beanClassSet = new HashSet<Class<?>>();
beanClassSet.addAll(getServiceClassSet());
beanClassSet.addAll(getControllerClassSet());
return beanClassSet;
}
/** * 获取应用包名下某父类(或接口)的所有子类(或实现类) * @param superClass * @return */ public static Set<Class<?>> getClassSetBySupper(Class<?> superClass){ Set<Class<?>> classSet = new HashSet<Class<?>>(); for (Class<?> cls : CLASS_SET){ if (superClass.isAssignableFrom(cls) && !superClass.equals(cls)){ classSet.add(cls); } } return classSet; } /** * 获取应用包名带有某注解的所有类 * @param annotationClass * @return */ 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类中编写一个带有Aspect注解的所有类,把封装成一个方法:
private static Set<Class<?>> createTargetClassSet(Aspect aspect)throws Exception{ Set<Class<?>> targetClassSet = new HashSet<Class<?>>(); Class<? extends Annotation> annotation = aspect.value(); if (annotation != null && annotation.equals(Aspect.class)){ targetClassSet.addAll(ClassHelper.getClassSetByAnnotation(annotation)); } return targetClassSet; }
获取Aspect注解中设置的注解类,若该注解类不是Aspect类,则可调用ClassHelper的getClassSetByAnnotation方法获取相关的类,并把这些类放入目标类集合中,最终返回这个集合。
紧接着我们需要获取代理类及其目标类集合之间的映射关系,一个代理类可对应一个或多个目标类。需要强调的是,这里所说的代理类指的是切面类。通过以下代码获取这个映射关系:
private static Map<Class<?>,Set<Class<?>>> createProxyMap()throws Exception{ Map<Class<?>,Set<Class<?>>> proxyMap = new HashMap<Class<?>, Set<Class<?>>>(); Set<Class<?>> proxyClassSet = ClassHelper.getClassSetBySupper(AspectProxy.class); for (Class<?> proxyClass: proxyClassSet) { if (proxyClass.isAssignableFrom(Aspect.class)){ Aspect aspect = proxyClass.getAnnotation(Aspect.class); Set<Class<?>> targetClassSet = createTargetClassSet(aspect); proxyMap.put(proxyClass,targetClassSet); } } return proxyMap; }
代理类需要扩展AspectProxy抽象类,还需要带有Aspect注解,只有满足这两个条件,才能根据Aspect注解中所定义的注解属性去获取该注解所对应的目标类集合,然后才能建立代理类与目标类集合之间的映射关系,最终返回这个映射关系
一旦获取了代理类与目标类集合之间的映射关系,就能根据这个关系分析出目标类与代理对象列表之间的映射关系,就像下面这样:
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) targetClass.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中通过一个静态块来初始化整个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(); Object proxy = ProxyManager.createProxy(targetClass,proxyList); BeanHelper.setBean(targetClass,proxy); } }catch (Exception e){ } }
获取代理类及其目标类集合的映射关系,进一步获取目标类与代理对象列表的映射关系,进而遍历这个映射关系,从中获取目标类与代理对象列表,调用ProxyManager.createProxy方法获取代理对象,调用BeanHelper.setBean方法,将该代理对象重新放入Bean Map中。
下面是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.*;
/**
* Created by jack on 2017/7/17.
*/
public final class AopHelper {
private static final Logger LOGGER = LoggerFactory.getLogger(AopHelper.class);
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();
Object proxy = ProxyManager.createProxy(targetClass,proxyList);
BeanHelper.setBean(targetClass,proxy);
}
}catch (Exception e){
LOGGER.error("load aop failure",e);
}
}
private static Set<Class<?>> createTargetClassSet(Aspect aspect)throws Exception{ Set<Class<?>> targetClassSet = new HashSet<Class<?>>(); 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<?>>>();
Set<Class<?>> proxyClassSet = ClassHelper.getClassSetBySupper(AspectProxy.class);
for (Class<?> proxyClass: proxyClassSet) {
if (proxyClass.isAssignableFrom(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) targetClass.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; /** * Created by jack on 2017/5/24. * 加载相应类的,帮助类 */ 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就开发完毕了。
github代码中的地址:https://github.com/wj903829182/smartframework
相关文章推荐
- 从零开始写javaweb框架笔记23-使框架具备AOP特性-实现事务控制特性
- 从零开始写javaweb框架笔记21-使框架具备AOP特性-ThreadLocal简介
- 从零开始写javaweb框架笔记22-使框架具备AOP特性-事务管理简介
- 从零开始写javaweb框架笔记18-使框架具备AOP特性-代理技术简介
- 从零开始写javaweb框架笔记19-使框架具备AOP特性-AOP技术简介
- [笔记]架构探险-从零开始写JavaWeb框架-2.2. 之使框架具有aop特性-干货,让框架支持事务处理
- [笔记]架构探险-从零开始写JavaWeb框架-2.1. 之使框架具有aop特性-aop框架加载与切面运行流程分析
- 从零开始写javaweb框架笔记7-动手开发web应用
- 从零开始写javaweb框架笔记13-搭建轻量级JAVAWEB框架-开发一个类加载器
- 从零开始写javaweb框架笔记11-搭建轻量级JAVAWEB框架-搭建开发环境
- 从零开始写javaweb框架笔记13-搭建轻量级JAVAWEB框架-开发一个类加载器
- 从零开始写javaweb框架笔记14-搭建轻量级JAVAWEB框架-实现Bean容器
- 从零开始写javaweb框架笔记15-搭建轻量级JAVAWEB框架-实现依赖注入功能
- 从零开始写javaweb框架笔记17-搭建轻量级JAVAWEB框架-请求转发
- 从零开始写javaweb框架笔记15-搭建轻量级JAVAWEB框架-实现依赖注入功能
- 从零开始写javaweb框架笔记12-搭建轻量级JAVAWEB框架-定义框架配置项,加载配置项
- 从零开始写javaweb框架笔记10-搭建轻量级JAVAWEB框架-确定目标
- 从零开始写javaweb框架笔记16-搭建轻量级JAVAWEB框架-加载Controller,初始化框架
- 从零开始写javaweb框架笔记9-细节完善与代码优化-完善控制器层
- 从零开始写javaweb框架笔记6-需求分析与系统设计