昨天写的一个业务上线了,但是在dev环境和test环境都能跑,但是到了线上环境发生 数据不能插入 的问题。
问了老大之后发现线上数据库是读写分离的,然后通过过滤器的才能进入写数据库卡,我的函数命名规范问题不符合过滤器的要求,导致从controller不能进入逻辑函数。
AOP目标是 把业务的共性问题 提取出来集中放到一个统一的地方管理和控制。
不同方法在java的完整周期(类加载期间,编译期,运行期间等)中 不同的时间段插入切面的方式不同 (即我们想要他在这个时间完成的方法,这里建议先了解 AOP的5种增强类型 )。
Cglib 是一个强大的,高性能的 Code 生成类库。 原理是在运行期间目标字节码加载后,通过字节码技术为一个类创建子类, 并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。 由于是通过子类来代理父类,因此不能代理被 final 字段修饰的方法。 复制代码
在java编译期间有不同的织入方法
对于AOP来说,最重要的点在于:
参考: juejin.im/post/5c0153…
1.将读操作和写操作分离到不同的数据库上,避免主服务器出现性能瓶颈; 2.主服务器进行写操作时,不影响查询应用服务器的查询性能,降低阻塞,提高并发; 3.数据拥有多个容灾副本,提高数据安全性。 4.同时当主服务器故障时,可立即切换到其他服务器,提高系统可用性; 复制代码
1、冷备份(定时全量/增量备份) 2、热备份(在主从架构上实现) 3、主从架构(N主M从) 4、读写分离(在主从架构上实现) 5、数据分片(分库分表(垂直分库 水平分表)) 复制代码
参考: www.jianshu.com/p/b7834c990…
1、Master将数据改变记录到二进制日志(binary log)中,也就是配置文件log-bin指定的文件,这些记录叫做二进制日志事件(binary log events) 2、Slave通过I/O线程读取Master中的binary log events并写入到它的中继日志(relay log) 3、Slave重做中继日志中的事件,把中继日志中的事件信息一条一条的在本地执行一次,完成数据在本地的存储,从而实现将改变反映到它自己的数据(数据重放) 复制代码
data所有数据源列表:master 写库 slave 读库 数据源DynamicDataSource类需要通过继承AbstractRoutingDataSource <bean id="dynamicDataSource" class="com.A.B.DynamicDataSource"> <property name="targetDataSources"> <map key-type="java.lang.String"> <entry key="master" value-ref="masterDataSource" /> <entry key="slave" value-ref="slaveDataSource" /> </map> </property> <property name="defaultTargetDataSource" ref="lingxu_masterDataSource" /> </bean> 配置dataAOP 动态设置数据源 <bean id="dataSourceAdvice" class="com.T.A.dsadvice.DataSourceAdvice" /> 配置事务 <!-- spring aop manager transaction --> <tx:advice id="txTransactionAdvice" transaction-manager="transactionManager"> <tx:attributes> <!-- add transaction --> <tx:method name="add*" propagation="REQUIRED" rollback-for="Exception"/> <tx:method name="create*" propagation="REQUIRED" rollback-for="Exception"/> <tx:method name="save*" propagation="REQUIRED" rollback-for="Exception"/> <tx:method name="insert*" propagation="REQUIRED" rollback-for="Exception"/> <tx:method name="update*" propagation="REQUIRED" rollback-for="Exception"/> <tx:method name="change*" propagation="REQUIRED" rollback-for="Exception"/> <tx:method name="modify*" propagation="REQUIRED" rollback-for="Exception"/> <tx:method name="edit*" propagation="REQUIRED" rollback-for="Exception"/> <tx:method name="delete*" propagation="REQUIRED" rollback-for="Exception"/> <tx:method name="remove*" propagation="REQUIRED" rollback-for="Exception"/> </tx:attributes> </tx:advice> 添加两个数据源至aop:config <aop:config> <aop:advisor advice-ref="dataSourceAdvice" pointcut="execution(* com.T.A.service..*Service.*(..))" order="1"/> <aop:advisor advice-ref="txTransactionAdvice" pointcut="execution(* com.T.A.service..*Service.*(..)))" order="2" /> </aop:config> 复制代码
//determineCurrentLookupKey是重写的AbstractRoutingDataSource的方法 //主要是确定当前应该使用哪个数据源的key,因为AbstractRoutingDataSource 中保存的多个数据源是通过Map的方式保存的 public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DataSourceSwitcher.getDataSource(); } } 复制代码
public class DataSourceAdvice implements MethodBeforeAdvice, AfterReturningAdvice, ThrowsAdvice 复制代码