spring aop
java代理模式分两种
委托类 代理类。 个人觉得好处:降低耦合。可以在委托类调用方法上 在不该源码的情况(框架也不可能修改) 自己定做(spring aop数据源切换)。更加灵活。
某著名国内狗粮(委托类)。然后国内总代(代理类) 事物也是用的代理模式
1静态代理
程序在运行态前已经有代理类
2动态代理
运行时才确定代理类
动态代理分两种
jdk代理 需要实现接口
//委托类继承接口
public class Proxy implement ISell{
...
}
//中介类
public class Agent implement InvocationHandler{
//调用代理类的方法时候 通过反射 调用委托类的方法
public ... invoke(Object proxy, Method method, Object[] objs) {
//随意增加代码
method.invoke(proxy/**委托类*/, objs);
//随意增加代码 开心就好
}
}
public void static Main(String[] args){
ISell iSell = (ISell)proxy.newPorxyInstance(ISell.getClassLoader()/**classloader*/, ISell.class/**接口*/, new Agent()/**代理类*/);
iSell.方法();
}
cglib代理 不需要实现接口
public AgentInterceptor implements MethodInterceptor{
public Object intercept(Object prxoyobj, Method method, Object[] arg, MethodProxy methodProxy){
//加代码
Object invokeSuper = methodProxy.invokeSuper(prxoyobj, arg);//调用父类的方法
//加代码
}
}
Enhancer en = new Enhancer();
en.setSuperclass(类);
en.setCallback(new Agent());
agentInterceptor = en.create();
agentInterceptor.方法的时候。 会通过回调函数的方式调用intercept方法。然后执行父类的那个方法。
spring aop是利用代理模式实现的例子。
spring aop概念
又称切面编程。java是面向对象的。是纵向的。切面编程是横向的。比如异常处理代码。日志代码。这些与业务代码无关的代码。散步在各个业务代码中,可能会造成冗余等。切面编程 就可以将这些代码串联起来。做一个统一的处理。然后在某些方法被调用的时候,提前处理。
切面 point aspect 需要执行代理代码的那些地方 增加上我们的代码 就是切面
切点point ponit 就是要在执行我们代理代码的哪些地方
通知 advice 前后通知 before after
引入 执行我们代理中的方法
spring的配置文件中可以配置这些
<aop:config>
<aop:aspect id="time" ref="timeHandler">
<aop:pointcut id="addAllMethod" expression="execution(* com.xrq.aop.HelloWorld.*(..))" />
<aop:before method="printTime" pointcut-ref="addAllMethod" />
<aop:after method="printTime" pointcut-ref="addAllMethod" />
</aop:aspect>
</aop:config>
springmvc aop 用到的地方 多个数据源 数据源切换 日志管理
数据源切换
通过对调用的save方法(save方法上+注解)前(传值设置不同的key),来调用不同的数据源
abstractroutingdatasource 里面有个关键方法
public Connection getConnection() throws SQLException {
return determineTargetDataSource().getConnection();
}
determineTargetDataSource方法
protected DataSource determineTargetDataSource() {
Assert.notNull(this.resolvedDataSources, "DataSource router not initialized");
Object lookupKey = determineCurrentLookupKey();
DataSource dataSource = this.resolvedDataSources.get(lookupKey);
if (dataSource == null && (this.lenientFallback || lookupKey == null)) {
dataSource = this.resolvedDefaultDataSource;
}
if (dataSource == null) {
throw new IllegalStateException("Cannot determine target DataSource for lookup key [" + lookupKey + "]");
}
return dataSource;
}
可以看出是通过determinecurrentlookupkey返回的key 来获得相应的datasource
这里可以通过aop 当调用我们的数据库方法时 ,提前执行我们的方法吧lookupkey换成想要执行那个库就好
加pointcut() 注解 可以拦截方法 或者 +某些自定注解。来截取相应的方法。在之前或者之后
调用dobefore

浙公网安备 33010602011771号