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

 

 

 

 

  

 

posted @ 2018-12-06 16:27  saveworld_niub  阅读(210)  评论(0)    收藏  举报