Spring IOC设计到的设计模式: 工厂模式,模板方法模式,单例模式
Spring AOP涉及到的设计模式: 工厂模式,代理模式
1、Spring AOP目标
将分散在程序各处的横切关注点剥离出来,并以集中的方式进行表达
使得开发人员专注于业务逻辑的实现而非繁杂的非功能代码,简化了程序编写与单元测试
应用场景:
日志
安全
事务
2、AOP核心概念
Advice(通知)
定义在连接点处的行为,围绕方法调用而进行注入
Pointcut(切点)
确定在哪些连接点处应用通知
Advisor(通知器)
组合Advice和Pointcut
3、Spirng AOP实现
ProxyFactoryBean
--FactoryBean implementation that builds an AOP proxy based on beans in Spring BeanFactory.
--Spring AOP的底层实现与源头
4、ProxyFactoryBean的典型配置
5、ProxyFactoryBean的构成
target
目标对象,需要对其进行切面增强
proxyInterfaces
代理对象所实现的接口
interceptorNames
通知器(Advisor)列表,通知器中包含了通知(Advice)与切入点(Pointcut)
6、ProxyFactoryBean的作用
总的来说,ProxyFactoryBean的作用可用下面这句话概括
针对目标对象来创建代理对象,将对目标对象方法的调用转到对相应代理对象方法的调用,并且可以在代理对象方法调用前后执行与之匹配的各个通知器定义好的方法。
7、目标代理对象的创建
Spring通过两种方式来创建目标对象
JDK动态代理
CGLIB
8、JDK动态代理
如果目标对象实现了接口,那么Spring就会通过JDK动态代理为目标对象生成代理对象
JdkDynamicAopProxy中getProxy方法
public Object getProxy(ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
}
Class[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
9、DefaultAopProxyFactory
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
if (targetClass.isInterface()) {
return new JdkDynamicAopProxy(config);
}
if (!cglibAvailable) {
throw new AopConfigException(
"Cannot proxy target class because CGLIB2 is not available. " +
"Add CGLIB to the class path or specify proxy interfaces.");
}
return CglibProxyFactory.createCglibProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
10、CGLIB代理(Cglib2AopProxy.java)
如果目标类并未实现接口,那么spring就好使用CGLIB库创建代理
创建代理对象
11、Spring AOP拦截(动态代理方式)
实际上是通过InvocationHandler的invoke方法实现的
JdkDynamicAopProxy类本身实现了InvocationHandler接口
JdkDynamicAopProxy类中的invoke方法中
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
获取配置的拦截器链
在该方式下,拦截器链中各个拦截器的调用时通过ReflectiveMethodInvocation对象中的proceed方法实现的
proceed方法是一个递归方法
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
} Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
}
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}