• Spring标签@Aspect-实现面向方向编程(@Aspect的多数据源自动加载)——SKY


       从Spring 2.0开始,可以使用基于schema及@AspectJ的方式来实现AOP。由于@Aspect是基于注解的,因此要求支持注解的5.0版本以上的JDK。

     环境要求:
        1. mybits的DB连接,实现动态多数据源的设置。
        2. service层实现数据访问。

     我们的目标是,如果用户调用Service层中任一方法,都配置其动态数据源Id。

    在此先来说一下AOP:

        AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。OOP引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力。也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系。例如日志功能。日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系。对于其他类型的代码,如安全性、异常处理和透明的持续性也是如此。这种散布在各处的无关的代码被称为横切(cross-cutting)代码,在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。

    简介

      前段时间写的java设计模式--代理模式,最近在看Spring Aop的时候,觉得于代理模式应该有密切的联系,于是决定了解下Spring Aop的实现原理。

      说起AOP就不得不说下OOP了,OOP中引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。但是,如果我们需要为部分对象引入公共部分的时候,OOP就会引入大量重复的代码。例如:日志功能。

      AOP技术利用一种称为“横切”的技术,解剖封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,这样就能减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处都基本相似。比如权限认证、日志、事务处理。

    下面说说@aspect实现的动态数据源配置:

    1.定义一个Aspect。

        必须使用@Aspect在类名之前注解。

        当用户调用com.accessor.service包中任一类的任一方法,在调用前,Spring将自动执行下面的doBefore()方法,以及Doafter()方法。

    这里数据源的选择是通过枚举实现的。

     1 /**
     2  * Created by Administrator on 2016/11/3.
     3  */
     4 @Component
     5 @Aspect
     6 public class MultipleDataSourceAspect{
     7     private static AtomicInteger counter = new AtomicInteger(0);
     8 
     9     @Before("execution(* com.accessor.service..*(..))")
    10     public void doBefore(JoinPoint joinPoint) throws Throwable {
    11         String className = joinPoint.getTarget().getClass().getName();
    12         if (className.contains("oracle")) {
    13             DataSourceContextHolder.setDataSourceType(DataSourceEnum.ORACLE_READ.getValue());
    14         } else if (className.contains("sqlserver")) {
    15             setMsDataSource(joinPoint.getArgs());
    16         }
    17         System.out.println("------------------begin"+counter.getAndIncrement() +"-----" + DataSourceContextHolder.getDataSourceType() + "--------thread:" + Thread.currentThread().getName()) ;
    18     }
    19     @After("execution(* com.accessor.service..*(..))")
    20     public void doAfter(JoinPoint joinPoint) throws Throwable {
    21         Object[] args = joinPoint.getArgs();
    22         if (args != null && args.length > 0) {
    23             if (args[0] instanceof Map) {
    24                 Map param = (Map) args[0];
    25                 param.remove("msHisFlag");
    26                 param.remove("tabNameSuffix");
    27             }
    28         }
    29         System.out.println("--------------------end------------------remove:" + DataSourceContextHolder.getDataSourceType());
    30         DataSourceContextHolder.clearDataSourceType();
    31     }
    32 
    33     //设置ms数据源
    34     private void setMsDataSource(Object[] args) {
    35         DataSourceEnum dataSourceEnum = null;
    36         if (args != null && args.length > 0) {
    37             if (args[0] instanceof Map) {
    38                 Map param = (Map) args[0];
    39                 String fundId = CommonUtil.convert(param.get("fundId"), String.class);
    40                 if (fundId != null) {
    41                     if ("1".equals(param.get("msHisFlag"))) {
    42                         String tabNameSuffix = DateUtil.dateToStr(new Date(), "_yyyy_MM");
    43                         param.put("tabNameSuffix", tabNameSuffix);
    44                         dataSourceEnum = CommonUtil.getMsDataSourceEnum(fundId, true);
    45                     } else {
    46                         dataSourceEnum = CommonUtil.getMsDataSourceEnum(fundId);
    47                     }
    48                 }
    49                 DataSourceContextHolder.setDataSourceType(dataSourceEnum.getValue());
    50             }
    51         }
    52 
    53         if (dataSourceEnum == null) {
    54             throw new RuntimeException("无法确定查询的sqlserver数据源");
    55         }
    56     }
    57 }
    View Code

    2.spring的文件配置

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4        xmlns:aop="http://www.springframework.org/schema/aop"
     5        xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="
     6                       http://www.springframework.org/schema/beans
     7                       http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
     8                       http://www.springframework.org/schema/context
     9                       http://www.springframework.org/schema/context/spring-context-3.2.xsd
    10                       http://www.springframework.org/schema/aop
    11                       http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">
    12 
    13 
    14     <!-- 自动扫描(自动注入) -->
    15     <context:annotation-config/>
    16     <context:component-scan base-package="com.eastmoney"/>
    17     <aop:aspectj-autoproxy proxy-target-class="true"/>
    18 
    19     <bean id="springContextUtil " class="com.eastmoney.accessor.util.SpringContextUtil"/>
    20 
    21     <!-- 引入mybatis属性配置文件 -->
    22     <import resource="spring-mybatis.xml"/>
    23 </beans>
    View Code

    3.mybatis的文件配置

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4        xmlns:tx="http://www.springframework.org/schema/tx"
     5        xsi:schemaLocation="http://www.springframework.org/schema/beans
     6                            http://www.springframework.org/schema/beans/spring-beans.xsd
     7                            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
     8 
     9     <!-- 动态数据源 -->
    10     <bean id="dataSource" class="com.eastmoney.accessor.datasource.DynamicDataSource">
    11         <property name="dsConfigFile" value="dataSource.xml"/>
    12     </bean>
    13 
    14     <!-- mybatis配置 -->
    15     <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    16         <property name="dataSource" ref="dataSource"/>
    17         <property name="mapperLocations" value="classpath*:mapper/*/*.xml"/>
    18         <property name="configLocation" value="classpath:/mybatis-config.xml"/>
    19     </bean>
    20 
    21     <!-- 自动创建映射器,不用单独为每个 mapper映射-->
    22     <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    23         <property name="basePackage" value="com.eastmoney.accessor.mapper"/>
    24         <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    25     </bean>
    26 
    27     <!-- 事务管理器配置,单数据源事务 -->
    28     <bean id="transactionManager"
    29           class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    30         <property name="dataSource" ref="dataSource"/>
    31     </bean>
    32 
    33     <tx:annotation-driven transaction-manager="transactionManager"/>
    34 
    35 </beans>
    View Code

    就这么简单而强大的Spring注解配置,非常感兴趣,下次去过一遍Spring的原理和注解的使用规则,有机会在和大家分享。

                                                                                                                                                                                               笔者:SKY-yong    2016/11/18

      

  • 相关阅读:
    leetcode-9-basic-binary search
    selection problem-divide and conquer
    leetcode-8-pointer
    leetcode-7-hashTable
    前端学习之——js解析json数组
    Google浏览器如何加载本地文件
    JAVA全栈工程师应具备怎样的知识体系?
    Java全栈工程师知识体系介绍
    数据可视化工具
    使用js的FileReader对象
  • 原文地址:https://www.cnblogs.com/xiaoyongsz/p/6077380.html
Copyright © 2020-2023  润新知