1. 程式人生 > >007-搭建框架-開發AOP框架

007-搭建框架-開發AOP框架

data fig 註意 定義 entryset logger asp eat exc

一、代碼地址

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

測試待後續

007-搭建框架-開發AOP框架