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();
}

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

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

2.2、搭建代理框架

  添加Proxy接口  

package com.lhx.smart.framework.proxy;

public interface Proxy {
    Object doProxy(ProxyChain proxyChain) throws Throwable;
}

  添加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;
    }
}

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

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

  增加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();
            }
        });
    }
}

  增加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(){
    }
}

  增加一个实现

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));
    }
}

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;
    }
}

  修改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);
    }
}

  修改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;
    }
}

  在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);
        }
    }
}

测试待后续

时间: 2024-07-28 17:37:13

007-搭建框架-开发AOP框架的相关文章

.Net常见的IOC框架及AOP框架

IOC框架 Unity:微软patterns&practicest团队开发的IOC依赖注入框架,支持AOP横切关注点. MEF(Managed Extensibility Framework):是一个用来扩展.NET应用程序的框架,可开发插件系统. Spring.NET:依赖注入.面向方面编程(AOP).数据访问抽象,.以及ASP.NET集成. Autofac:最流行的依赖注入和IOC框架,轻量且高性能,对项目代码几乎无任何侵入性. Ninject:基于.NET轻量级开源的依赖注入IOC框架 A

mui框架开发aop的跨页面传值

mui开发跨平台app,其实不乏会涉及到跨页面传值,今天给大家简单介绍一种常用也是简单的传值方法 咱在这里设置一个场景,就是两个页面进入到同一页面展示不同的元素,此时需要在这两个页面各自设置一个区别的标签传递到那个要进入的页面,此时写法如下: 其中一个页面的传值如下: mui.openWindow({ //要跳转的页面地址 url: 'newsShow.html', //要跳转的页面id d: 'newsShow', //页面出现方式 show: { aniShow: 'pop-in' }, /

Django框架开发-web框架

一.web框架 web框架(web framwork)是一种开发框架,用来支持动态网站,网络应用和网络服务的开发.这大多数的web框架提供了一套开发和部署网站的方式,也为web行为提供了一套通用的方法.web框架已经实现了很多功能,开发人员使用框架提供的方法并且完成自己的业务逻辑,就能快速开发web应用了.浏览器和服务器的是基于HTTP协议进行通信的.也可以说web框架就是在以上十几行代码基础张扩展出来的,有很多简单方便使用的方法,大大提高了开发的效率. 二.wsgir模块 最简单的Web应用就

跟我学框架开发-简单框架蓝图

以下是一个简单早期的框架结构图,到目前为上已经作了太多的调整与进化.但基本的构件与原理不变: 个人觉得有以下几点: 1.要有基础框架建模平台,这是构件化的实现基础,也是本框架最重要的部分 2.全接口化交互,统一数据报文格式,内外部均全采用接口化数据交互 3.要进行多种分布式服务切割与API封装 4.强调数据路由功能,统一的数据总线交互模式,方便作数据监控.拦截.分发.切换 5.数据库与缓存(或MongoDB) 一键切换启用机制 6.数据库部分也是重中之重,后期再细讲

基于C/S架构的3D对战网络游戏C++框架 _05搭建系统开发环境与Boost智能指针、内存池初步了解

本系列博客主要是以对战游戏为背景介绍3D对战网络游戏常用的开发技术以及C++高级编程技巧,有了这些知识,就可以开发出中小型游戏项目或3D工业仿真项目. 笔者将分为以下三个部分向大家介绍(每日更新): 1.实现基本通信框架,包括对游戏的需求分析.设计及开发环境和通信框架的搭建: 2.实现网络底层操作,包括创建线程池.序列化网络包等: 3.实战演练,实现类似于CS反恐精英的3D对战网络游戏: 技术要点:C++面向对象思想.网络编程.Qt界面开发.Qt控件知识.Boost智能指针.STL算法.STL.

[Spring框架]Spring AOP基础入门总结二:Spring基于AspectJ的AOP的开发.

前言: 在上一篇中: [Spring框架]Spring AOP基础入门总结一. 中 我们已经知道了一个Spring AOP程序是如何开发的, 在这里呢我们将基于AspectJ来进行AOP 的总结和学习. 一, AspectJ的概述: AspectJ是一个面向切面的框架,它扩展了Java语言.AspectJ定义了AOP语法所以它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件. Spring为了简化自身的AOP的开发,将AspectJ拿过来作为Spring自身一个AOP的开发.

java开发SSM框架的搭建(SpringMVC+Spring+MyBatis)

由于某些原因,重装系统,java-web开发虽然顺手,但烦人的一点是开发环境的搭建.差不多折腾了一整天,笔者在这里把SSM开发环境的搭建重新清理一遍,以飨读者,也供自己以后参考.善于总结,是做好每份工作必备的素质之一. 1安装java虚拟机-JDK(1.7_51) 详见笔者博文:http://blog.csdn.net/gisredevelopment/article/details/24304085 2 安装MyEclipse(2014专业版) 下载地址:http://www.myeclips

一、搭建自己的开发小框架之构思

入IT这行许久,但一直毫无建树.为何?国人的惯性思维而已! 今早起来,瞬间冒出一想法,为何自己不做一个与功能性有关的.一键式的开发小框架.本人做了几年的研发,随时会遇到有各种功能性软件的需求.如果自己有一套可以一键自动生成某些功能的开发框架,那么每次开发起来岂不是可以减少大量重复搭建框架的操作. 就拿最简单的例子来说,此操作共计4步: 1.导入Execl文件: 2.筛选数据: 3.计算结果: 4.导出Excel文件. 如果一般性开发的话,首选还要寻找能操作Excel的dll文件,其次,还要cop

Unity3D热更新全书-脚本(四) 用C#LightEvil搭建实际开发使用的脚本框架

C#LightEvil之前提供了很多和Unity结合的例子,都是采用把脚本文件放置在StreamingAssets中的方法. 这样可以利用Unity的特性,放在这个目录中的CS文件会被编译器编译,我们就利用C#编译器来对我们的脚本进行验证. 同时StreamingAssets中的文件又是直接随项目发布的,所以可以直接以文件方式取出这些脚本文件编译执行. 这是一个很巧妙的方式,但是用在实际项目中会有一些问题: 一.可能会让程序员产生混淆,哪里是脚本,哪里是程序,傻傻分不清楚 二.主程序里会有一份用