从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()方法。

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

 /**
* Created by Administrator on 2016/11/3.
*/
@Component
@Aspect
public class MultipleDataSourceAspect{
private static AtomicInteger counter = new AtomicInteger(0); @Before("execution(* com.accessor.service..*(..))")
public void doBefore(JoinPoint joinPoint) throws Throwable {
String className = joinPoint.getTarget().getClass().getName();
if (className.contains("oracle")) {
DataSourceContextHolder.setDataSourceType(DataSourceEnum.ORACLE_READ.getValue());
} else if (className.contains("sqlserver")) {
setMsDataSource(joinPoint.getArgs());
}
System.out.println("------------------begin"+counter.getAndIncrement() +"-----" + DataSourceContextHolder.getDataSourceType() + "--------thread:" + Thread.currentThread().getName()) ;
}
@After("execution(* com.accessor.service..*(..))")
public void doAfter(JoinPoint joinPoint) throws Throwable {
Object[] args = joinPoint.getArgs();
if (args != null && args.length > 0) {
if (args[0] instanceof Map) {
Map param = (Map) args[0];
param.remove("msHisFlag");
param.remove("tabNameSuffix");
}
}
System.out.println("--------------------end------------------remove:" + DataSourceContextHolder.getDataSourceType());
DataSourceContextHolder.clearDataSourceType();
} //设置ms数据源
private void setMsDataSource(Object[] args) {
DataSourceEnum dataSourceEnum = null;
if (args != null && args.length > 0) {
if (args[0] instanceof Map) {
Map param = (Map) args[0];
String fundId = CommonUtil.convert(param.get("fundId"), String.class);
if (fundId != null) {
if ("1".equals(param.get("msHisFlag"))) {
String tabNameSuffix = DateUtil.dateToStr(new Date(), "_yyyy_MM");
param.put("tabNameSuffix", tabNameSuffix);
dataSourceEnum = CommonUtil.getMsDataSourceEnum(fundId, true);
} else {
dataSourceEnum = CommonUtil.getMsDataSourceEnum(fundId);
}
}
DataSourceContextHolder.setDataSourceType(dataSourceEnum.getValue());
}
} if (dataSourceEnum == null) {
throw new RuntimeException("无法确定查询的sqlserver数据源");
}
}
}

2.spring的文件配置

 <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd"> <!-- 自动扫描(自动注入) -->
<context:annotation-config/>
<context:component-scan base-package="com.eastmoney"/>
<aop:aspectj-autoproxy proxy-target-class="true"/> <bean id="springContextUtil " class="com.eastmoney.accessor.util.SpringContextUtil"/> <!-- 引入mybatis属性配置文件 -->
<import resource="spring-mybatis.xml"/>
</beans>

3.mybatis的文件配置

 <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- 动态数据源 -->
<bean id="dataSource" class="com.eastmoney.accessor.datasource.DynamicDataSource">
<property name="dsConfigFile" value="dataSource.xml"/>
</bean> <!-- mybatis配置 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mapperLocations" value="classpath*:mapper/*/*.xml"/>
<property name="configLocation" value="classpath:/mybatis-config.xml"/>
</bean> <!-- 自动创建映射器,不用单独为每个 mapper映射-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.eastmoney.accessor.mapper"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean> <!-- 事务管理器配置,单数据源事务 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean> <tx:annotation-driven transaction-manager="transactionManager"/> </beans>

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

笔者:SKY-yong    2016/11/18

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

  1. 【PHP面向对象(OOP)编程入门教程】23.自动加载类 __autoload()函数

    很多开发者写面向对象的应用程序时,对每个类的定义建立一个 PHP 源文件.一个很大的烦恼是不得不在每个脚本(每个类一个文件)开头写一个长长的包含文件的列表. 在软件开发的系统中,不可能把所有的类都写在 ...

  2. 说明反转控制(IOC)和面向方向编程(AOP)在spring中的应用

    说明反转控制(IOC)和面向方向编程(AOP)在spring中的应用 解答:Spring 核心容器(Core)提供Spring框架的基本功能.核心容器的主要组件是BeanFactory,它是工厂模式的 ...

  3. Spring boot 国际化自动加载资源文件问题

    Spring boot 国际化自动加载资源文件问题 最近在做基于Spring boot配置的项目.中间遇到一个国际化资源加载的问题,正常来说只要在application.properties文件中定义 ...

  4. spring的applicationContext.xml如何自动加载

    一个web工程自动加载的配置文件只有web.xml,想要加载其他.xml必须在web.xml里面进行配置. 用spring的时候需要一个bean容器来管理所有的bean,所有bean默认是写在appl ...

  5. ssh整合思想初步 struts2与Spring的整合 struts2-spring-plugin-2.3.4.1.jar下载地址 自动加载Spring中的XML配置文件 Struts2下载地址

    首先需要JAR包 Spring整合Structs2的JAR包 struts2-spring-plugin-2.3.4.1.jar 下载地址 链接: https://pan.baidu.com/s/1o ...

  6. 面向切面编程 ( Aspect Oriented Programming with Spring )

    Aspect Oriented Programming with Spring 1. 简介 AOP是与OOP不同的一种程序结构.在OOP编程中,模块的单位是class(类):然而,在AOP编程中模块的 ...

  7. Spring学习笔记:面向切面编程AOP(Aspect Oriented Programming)

    一.面向切面编程AOP 目标:让我们可以“专心做事”,避免繁杂重复的功能编码 原理:将复杂的需求分解出不同方面,将公共功能集中解决 *****所谓面向切面编程,是一种通过预编译方式和运行期动态代理实现 ...

  8. 关于spring.net的面向切面编程 (Aspect Oriented Programming with Spring.NET)-简介

    本文翻译自Spring.NET官方文档Version 1.3.2. 受限于个人知识水平,有些地方翻译可能不准确,但是我还是希望我的这些微薄的努力能为他人提供帮助. 侵删. 简介 Aspect-Orie ...

  9. 关于spring.net的面向切面编程 (Aspect Oriented Programming with Spring.NET)-切入点(pointcut)API

    本文翻译自Spring.NET官方文档Version 1.3.2. 受限于个人知识水平,有些地方翻译可能不准确,但是我还是希望我的这些微薄的努力能为他人提供帮助. 侵删. 让我们看看 Spring.N ...

随机推荐

  1. Linux用户配置sudo权限(visudo)

    sudo的工作过程如下: 1,当用户执行sudo时,系统会主动寻找/etc/sudoers文件,判断该用户是否有执行sudo的权限 2,确认用户具有可执行sudo的权限后,让用户输入用户自己的密码确认 ...

  2. python软件工程知识

    软件工程知识 3.1 程序设计过程中,常用伪代码来"思考"一个程序,在将伪代码程序转换成python程序. 3.2 所有python程序都可以给予6类控制结构来创建(顺序,if, ...

  3. Hibernate分页功能数据重复问题

    今天遇到一个很憋屈的问题那就是hibernate分页查询中出现重复数据,本来一直没有在意,以为是数据问题,但是一查程序和数据都没有问题,继续深入查看,找到问题了就是order By 时出的问题,唉.. ...

  4. DTD 和 Schema简介

    什么是DTD? DTD(文档类型定义)的作用是定义 XML 文档的合法构建模块. 它使用一系列的合法元素来定义文档结构. DTD例子 <?xml version="1.0"? ...

  5. fabricjs 自定义类型

    https://stackoverflow.com/questions/36660108/how-to-create-custom-fabricjs-object I have to create a ...

  6. Jenkins 安装卡住不动的解决方案

    如果在安装jenkins时卡在getting startted的界面,如下所示 jenkins在安装插件前总是尝试连接www.google.com,来判断网络是否连通.谷歌的网站在大陆是连不上的,所以 ...

  7. 如何使用CodeSmith批量生成代码

    在上一篇我们已经用PowerDesigner创建好了需要的测试数据库,下面就可以开始用它完成批量代码生成的工作啦. 下面我会一步步的解释如何用CodeSmith实现预期的结果的,事先声明一下,在此只做 ...

  8. java清除所有微博短链接 Java问题通用解决代码

    java实现微博短链接清除,利用正则,目前只支持微博短链接格式为"http://域名/字母或数字8位以内"的链接格式,现在基本通用 如果链接有多个,返回结果中会有多出的空格,请注意 ...

  9. java读取clob字段的几种方法

    http://cache.baiducontent.com/c?m=9f65cb4a8c8507ed4fece7631046893b4c4380143fd3d1027fa3c215cc790f1a06 ...

  10. MongoDB 常见的查询索引

    常见的查询索引 _id索引         _id 索引是绝大多数集合默认建立的索引.对于每一个插入的数据.MongoDB 会自己主动生成一条唯一的 _id 字段. 1 2 3 4 5 6 7 8 9 ...