zoukankan      html  css  js  c++  java
  • 007-搭建框架-开发AOP框架

    一、代码地址

    https://github.com/bjlhx15/smart-framework.git

    二、代码编写

    2.1、定义切面注解

    增加Aspect注解

    package com.lhx.smart.framework.annotation;
    
    import java.lang.annotation.*;
    
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Aspect {
        Class<? extends Annotation> value();
    }
    View Code

    注意:通过@Target(ElementType.TYPE)来设置该注解只能用在类上,该注解包含一个名为value的属性,他是一个注解用来定义Controller这类注解。

    在使用切面注解,需要搭建一个代理框架。如下

    2.2、搭建代理框架

      添加Proxy接口  

    package com.lhx.smart.framework.proxy;
    
    public interface Proxy {
        Object doProxy(ProxyChain proxyChain) throws Throwable;
    }
    View Code

      添加ProxyChain代理执行链

    package com.lhx.smart.framework.proxy;
    
    import net.sf.cglib.proxy.MethodProxy;
    
    import java.lang.reflect.Method;
    import java.util.ArrayList;
    import java.util.List;
    
    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;
    
        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;
        }
    }
    View Code

      注意MethodProxy是CGLib提供,需要增加注解POM

            <dependency>
                <groupId>cglib</groupId>
                <artifactId>cglib</artifactId>
                <version>3.1</version>
            </dependency>
    View Code

      增加ProxyManager类

    package com.lhx.smart.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;
    
    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[] objects, MethodProxy methodProxy) throws Throwable {
                    return new ProxyChain(targetClass, targetObject, targetMethod, methodProxy, objects, proxyList).doProxyChain();
                }
            });
        }
    }
    View Code

      增加AspectProxy代理

    package com.lhx.smart.framework.proxy;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import java.lang.reflect.Method;
    
    
    public abstract 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,result);
                }else{
                    result = proxyChain.doProxyChain();
                }
            } catch (Exception e) {
                logger.error("proxy failure",e);
                error(cls,method,params,e);
                throw e;
            } finally {
                end();
            }
            return result;
        }
        public void begin(){
        }
        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,Object result) throws Throwable{
        }
        public void error(Class<?> cls,Method method,Object[] params,Throwable e){
        }
        public void end(){
        }
    }
    View Code

      增加一个实现

    package com.lhx.chapter4.aspect;
    
    import com.lhx.smart.framework.annotation.Aspect;
    import com.lhx.smart.framework.annotation.Controller;
    import com.lhx.smart.framework.proxy.AspectProxy;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import java.lang.reflect.Method;
    
    @Aspect(Controller.class)
    public class ControllerAspect extends AspectProxy {
        private  static  final Logger logger = LoggerFactory.getLogger(ControllerAspect.class);
        private long begin;
        @Override
        public void before(Class<?> cls, Method method, Object[] params) throws Throwable {
            logger.debug("----begin-----");
            begin = System.currentTimeMillis();
        }
    
        @Override
        public void after(Class<?> cls, Method method, Object[] params, Object result) throws Throwable {
            logger.debug(String.valueOf(System.currentTimeMillis()-begin));
        }
    }
    View Code

    2.3、加载AOP

      增加AopHelper类

    package com.lhx.smart.framework.helper;
    
    import com.lhx.smart.framework.annotation.Aspect;
    import com.lhx.smart.framework.proxy.AspectProxy;
    import com.lhx.smart.framework.proxy.Proxy;
    import com.lhx.smart.framework.proxy.ProxyManager;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import sun.util.resources.cldr.ti.CalendarData_ti_ER;
    
    import java.lang.annotation.Annotation;
    import java.util.*;
    
    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("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<?>, 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;
        }
    
        private static Map<Class<?>, Set<Class<?>>> createProxyMap() throws Exception {
            Map<Class<?>, Set<Class<?>>> proxyMap = new HashMap<Class<?>, Set<Class<?>>>();
            Set<Class<?>> proxyClassSet = ClassHelper.getClassSetBySuper(AspectProxy.class);
    
            for (Class<?> proxyClass : proxyClassSet) {
                if (proxyClass.isAnnotationPresent(Aspect.class)) {
                    Aspect aspect = proxyClass.getAnnotation(Aspect.class);
                    Set<Class<?>> targetClassSet = createTargetClassSet(aspect);
                    proxyMap.put(proxyClass, targetClassSet);
                }
            }
    
            return proxyMap;
        }
    }
    View Code

      修改BeanHelper

    package com.lhx.smart.framework.helper;
    
    import com.lhx.smart.framework.util.ReflectionUtil;
    
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Set;
    
    public final class BeanHelper {
    
        /**
         * 定义bena映射(用于存放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 obj = ReflectionUtil.newInstance(beanClass);
                BEAN_MAP.put(beanClass, obj);
            }
        }
        public static void setBean(Class<?> cls,Object obj){
            BEAN_MAP.put(cls,obj);
        }
    
    
        public static Map<Class<?>, Object> getBeanMap() {
            return BEAN_MAP;
        }
    
        public static <T> T getBean(Class<T> cls) {
            if (!BEAN_MAP.containsKey(cls)) {
                throw new RuntimeException("没有此bean的实例" + cls);
            }
            return (T) BEAN_MAP.get(cls);
        }
    }
    View Code

      修改Classhelper

    package com.lhx.smart.framework.helper;
    
    import com.lhx.smart.framework.annotation.Controller;
    import com.lhx.smart.framework.annotation.Service;
    import com.lhx.smart.framework.util.ClassUtil;
    
    import java.lang.annotation.Annotation;
    import java.util.HashSet;
    import java.util.Set;
    
    /**
     * 类操作助手类
     */
    public class ClassHelper {
        /**
         * 定义类集合(用于存放所加载的类)
         */
        private static final Set<Class<?>> CLASS_SET;
    
        static {
            String basePackage = ConfigHelper.getAppBasePackage();
            CLASS_SET = ClassUtil.getClassSet(basePackage);
        }
    
        /**
         * 获取应用报名下的所有类
         *
         * @return
         */
        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类
         */
        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<?>> getClassSetBySuper(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;
        }
    }
    View Code

      在HelperLoader增加启动  

    package com.lhx.smart.framework;
    
    import com.lhx.smart.framework.helper.*;
    import com.lhx.smart.framework.util.ClassUtil;
    
    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);
            }
        }
    }
    View Code

    测试待后续

  • 相关阅读:
    重构原则
    【重构:改善既有代码的设计】读书笔记——开篇
    C#值参数和引用参数
    使用Aspose.Cells利用模板导出Excel(C#)
    在MVC中使用rdlc格式的报表
    程序员如何高效学习
    IT 圈里有哪些经常被读错的词?
    VS2017生成解决方案报错,提示对路径的访问被拒绝
    JavaScript中的数值转换
    Xadmin的配置及使用
  • 原文地址:https://www.cnblogs.com/bjlhx/p/7834899.html
Copyright © 2011-2022 走看看