`
huangshihang
  • 浏览: 12283 次
社区版块
存档分类
最新评论

《架构探险》之面向切面编程(AOP)(下)

阅读更多

        spring主要的特点之一就是面向切面编程,为了实现切面编程需要借助动态代理技术。

        首先,定义一个代理管理类,用来创建创建的代理,在代理中调用切面的实现逻辑:

public class ProxyManager {

    public static <T> T createProxy(final Class<?> targetClass, final List<Proxy> proxyList){
        return (T) Enhancer.create(targetClass, new MethodInterceptor() {
            @Override
            public Object intercept(Object targetObject, Method targetMethod, Object[] methodParams, MethodProxy methodProxy) throws Throwable {
                return new ProxyChain(targetClass, targetObject, targetMethod, methodProxy, methodParams, proxyList).doProxyChain();
            }
        });
    }
}

         多个切面使用链表来管理,组成一个切面链,:

public Object doProxyChain() throws Throwable {
    Object methodResult;
    if(proxyIndex < proxyList.size()){
        Proxy proxy = proxyList.get(proxyIndex);
        proxyIndex++;
        methodResult = proxy.doProxy(this);
    }else {
        methodResult = methodProxy.invokeSuper(targetObject,      methodParams);
    }

    return methodResult;
}

         以事务切面的实现为例:

public class TransactionAspect extends AspectProxy {

    private static final Logger LOGGER = LoggerFactory.getLogger(AspectProxy.class);
    private static final ThreadLocal<Boolean> FLAG_HOLDER = new ThreadLocal<Boolean>();

    @Override
    public final Object doProxy(ProxyChain proxyChain)throws Throwable{
        Object result = null;

        Method method = proxyChain.getTargetMethod();
        Boolean flag = FLAG_HOLDER.get();
        if(flag == null && method.isAnnotationPresent(Transaction.class)){
            try {
                  FLAG_HOLDER.set(true);
                  DatabaseHelper.beginTransaction();
                  result = proxyChain.doProxyChain();
                  DatabaseHelper.endTransaction();
            } catch (Exception e) {
                  LOGGER.error("proxy failure", e);
                  DatabaseHelper.rollbackTransaction();
                  throw e;
            } finally {
                  FLAG_HOLDER.remove();
            }
         }else {
             result = proxyChain.doProxyChain();
         }

        return result;
    }

}

        接下来,就需要在框架的对象管理池中在切点出使用动态代理替代原有的对象,这样当调用对象方法时会去调用代理的处理逻辑,实现面向切面的编程。

//根据代理类找到目标类,然后反过来对目标类生成代理类(链)

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) {
        e.printStackTrace();
    }
}

private static Set<Class<?>> createTargetClassSet(Aspect aspect){
    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(){
    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);
        }
    }
    Set<Class<?>> transactionServiceSet = ClassHelper.getClassSetByAnnotation(Service.class);
    proxyMap.put(TransactionAspect.class, transactionServiceSet);

    return proxyMap;
}

private static Map<Class<?>, List<Proxy>> createTargetMap(Map<Class<?>, Set<Class<?>>> proxyMap) throws IllegalAccessException, InstantiationException {
    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;
}

 

 

分享到:
评论

相关推荐

    架构探险 从零开始写javaweb框架-pdf及源码.rar

    在Spring部分,书中会详细讲解Spring框架的核心组件,如依赖注入(DI)、面向切面编程(AOP)和Spring MVC。依赖注入是Spring的核心特性,它使得对象之间的关系在运行时动态绑定,提高了代码的可测试性和可维护性。...

    架构探险,从零开始写javaweb框架-源码

    7. **AOP(面向切面编程)**:面向切面编程允许我们在不修改原有代码的情况下,添加新的功能或进行日志记录、性能监控等操作。Smart框架可能通过实现AspectJ或Spring AOP来实现这一特性。 8. **国际化与本地化**:...

    架构探险+从零开始写javaweb框架.pdf

    4. **AOP(面向切面编程)**:学习如何使用切面编程来实现跨切面的关注点,比如日志记录、事务管理等,使得代码更加模块化。 5. **持久层技术**:书中可能会涉及数据库操作,如JDBC、MyBatis或Hibernate,这些都是...

    架构探险 从零开始写javaweb框架 源码

    8. **AOP(面向切面编程)**:AOP允许我们定义横切关注点,如日志记录、事务管理等,使其与业务代码解耦。我们将探讨如何在框架中实现AOP机制。 9. **会话管理**:为了保持用户状态,Web应用常常需要使用会话。我们...

    架构探险javaweb

    6. **Spring框架**:Spring是Java企业级应用的事实标准,提供了依赖注入、AOP(面向切面编程)、事务管理、数据访问和Web MVC框架。深入理解Spring Boot和Spring Cloud还能帮助开发者快速构建微服务架构。 7. **...

    架构探险 从零开始写javaweb框架Pdf及书上源码

    6. ** IOC与AOP**:控制反转(IOC)和面向切面编程(AOP)是Spring框架的核心特性。通过IOC容器,可以实现依赖注入,简化对象之间的依赖关系;AOP则用于分离关注点,如日志记录、权限控制等。书中会详细讲解这两个...

    架构探险—从零开始写Java Web框架

    10. **AOP(面向切面编程)**:利用AOP实现日志记录、事务管理等功能,使得代码更加模块化,提高可维护性。 11. **数据库集成**:介绍JDBC基础,以及ORM(对象关系映射)框架如Hibernate或MyBatis,简化数据库操作...

    架构探险_从零开始学spring

    Spring框架以其依赖注入(Dependency Injection,DI)和面向切面编程(Aspect-Oriented Programming,AOP)为核心,简化了Java应用的开发。在书中,作者首先会介绍Spring的基本理念和框架结构,包括IoC容器和Bean的...

    架构探险 从零开始写javaweb框架

    6. **AOP(面向切面编程)**:JavaWeb框架中,AOP常用于日志记录、权限控制等横切关注点。书中会讲解AOP的概念和实现,以及如何在自定义框架中实现类似功能。 7. **持久层技术**:对于数据存储,书中可能涉及数据库...

    架构探险:从零开始写JavaWeb框架

    6. **Spring框架基础**:虽然标题强调从零开始,但了解Spring框架的基本概念和工作原理,如依赖注入(DI)和面向切面编程(AOP),将有助于理解JavaWeb框架的设计思想。 7. **数据库连接与JDBC**:JavaWeb框架通常...

    架构探险从零开始javaweb框架

    1. Spring框架:除了Spring MVC,Spring还提供了依赖注入、AOP(面向切面编程)、数据访问/集成、任务调度等多种功能,是构建企业级应用的基石。 2. Hibernate和MyBatis:持久层框架如Hibernate和MyBatis简化了...

    架构探险 从零开始写javaweb框架 源代码

    拦截器通常用于AOP(面向切面编程),如权限检查、日志记录等;过滤器则常用于数据的转换、编码、安全过滤等。 6. **依赖注入**: 为了实现代码的松耦合,依赖注入(DI)是一种常用的设计模式。Spring框架的IoC...

    jgtx:架构探险从零开始写Java Web框架

    - AOP(面向切面编程):允许开发者定义横切关注点,如性能监控、日志记录、异常处理等。 - 数据校验:提供数据验证机制,确保输入的有效性。 - i18n(国际化):支持多语言环境,便于应用的全球化。 - IOC...

    架构相关书籍推荐.zip

    5. **AOP(面向切面编程)**:学习如何使用切面来组织代码,提高代码的可维护性和可重用性。 6. **持久层框架**:如Hibernate或MyBatis,用于数据库操作,理解ORM(对象关系映射)的概念。 接下来,我们转向《从...

    java深度历险

    Spring提供了依赖注入、AOP(面向切面编程)、MVC(模型-视图-控制器)架构等核心功能,有助于简化开发流程并提高代码的可测试性。你还将学习如何配置和使用Spring Boot,这是一个快速开发工具,可以简化Spring应用...

Global site tag (gtag.js) - Google Analytics