AOP基本概述
Advice(通知)
- BeforeAdvice
package org.springframework.aop;
import java.lang.reflect.Method;
public interface MethodBeforeAdvice extends BeforeAdvice {
void before(Method method, Object[] args, Object target) throws Throwable;
}
before是回调方法,在Advice中配置了目标方法后,会在调用目标方法时被回调。
参数:
method:目标方法
args:目标方法的输入参数
target:目标对象
- AfterReturningAdvice
package org.springframework.aop;
import java.lang.reflect.Method;
public interface AfterReturningAdvice extends AfterAdvice {
void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable;
}
在目标方法调用结束并正常返回时,接口被回调
- ThrowsAdvice
public interface ThrowsAdvice extends AfterAdvice {
}
抛出异常时被回调,AOP使用反射实现(方法名叫AfterThrowing?)
PointCut(切入点)
public interface Pointcut {
ClassFilter getClassFilter();
MethodMatcher getMethodMatcher();
Pointcut TRUE = TruePointcut.INSTANCE;
}
PointCut是通过MethodMatcher 进行切入点方法匹配的,判断是否需要对当前方法进行增强处理。
通过JdkRegexpMethodPointcut理解MethodMatcher:
在JdkRegexpMethodPointcut的基类StaticMethodMatcherPointcut中设置MethodMatcher为StaticMethodMatcherPointcut(StaticMethodMatcher)
public abstract class StaticMethodMatcherPointcut extends StaticMethodMatcher implements Pointcut {
@Override
public final MethodMatcher getMethodMatcher() {
return this;
}
}
在JdkRegexpMethodPointcut中通过正则表达式匹配需要增强的方法:
protected boolean matches(String pattern, int patternIndex) {
Matcher matcher = this.compiledPatterns[patternIndex].matcher(pattern);
return matcher.matches();
}
在NameMatchMethodPointcut中通过方法名进行方法的匹配:
@Override
public boolean matches(Method method, Class<?> targetClass) {
for (String mappedName : this.mappedNames) {
if (mappedName.equals(method.getName()) || isMatch(method.getName(), mappedName)) {
return true;
}
}
return false;
}
protected boolean isMatch(String methodName, String mappedName) {
return PatternMatchUtils.simpleMatch(mappedName, methodName);
}
Advisor(通知器)
通知器负责把切入点和增强处理接合起来。
在切点处决定使用哪个通知
AOP设计与实现
JVM动态代理
JDK和CGLIB都是用动态代理实现的
AopProxy代理对象
Spring中,是通过ProxyFactoryBean来完成代理对象的生成的
- ProxyConfig
数据基类,为ProxyFactoryBean这样的子类提供配置属性。
- AdvisedSupport
AOP对通知和通知器的操作,对不同的AOP代理的生成都是一样的。对于具体生代理类,由AdvisedSupport的子类来做。
- ProxyCreatorSupport
子类创建AOP代理类的辅助
- ProxyFactoryBean
IOC容器中声明式配置,生成代理类
- ProxyFactory
编程式使用,生成代理类
- AspectJProxyFactory
需要使用AspectJ功能的AOP应用,这个起到集成Spring和AspectJ的作用
具体AOP代理对象的生成是由ProxyFactoryBean、ProxyFactory、AspectJProxyFactory完成的。
如何配置ProxyFactory?
<bean id="testAdvisor" class="com.abc.TestAdvisor" />
<!-- 通知器,实现了目标对象需要增强的切面行为,也就是通知 -->
<bean id="testAop" class="org.springframework.aop.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>com.test.AbcInterface</value>
</property>
<property name="target">
<!-- 目标对象 -->
<bean class="com.abc.TestTarget" />
</property>
<property name="interceptorNames">
<!-- 需要拦截的方法接口,通知器 -->
<list>
<value>
testAdvisor
</value>
</list>
</property>
</bean>
代理对象获取入口:
ProxyFactoryBean的getObject
AopProxy生成过程:
ProxyFactoryBean的getObject获取代理对象
@Override
public Object getObject() throws BeansException {
//初始化通知器链,为代理对象配置通知器链。
initializeAdvisorChain();
//区分SingleTon和ProtoType,生成对应的Proxy
if (isSingleton()) {
return getSingletonInstance();
} else {
if (this.targetName == null) {
logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +
"Enable prototype proxies by setting the ‘targetName‘ property.");
}
return newPrototypeInstance();
}
}
关于initializeAdvisorChain
这个初始化过程有一个标志位advisorChainInitialized,这个标志用来表示通知器链是否已经初始化。
如果已经初始化,那么这里不会再初始化,直接返回。初始化只是在应用第一次通过ProxyFactoryBean获取代理对象的时候。
完成这个初始化之后,接着会读取配置中出现的所有通知器(把通知器的名字交给容器的getBean,IOC容器的回调获取通知器),把通知器加入拦截器链(addAdvisoronChainCreation实现)。
private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
if (this.advisorChainInitialized) {
return;
}
if (!ObjectUtils.isEmpty(this.interceptorNames)) {
if (this.beanFactory == null) {
throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
"- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));
}
// Globals can‘t be last unless we specified a targetSource using the property...
if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) &&
this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {
throw new AopConfigException("Target required after globals");
}
// Materialize interceptor chain from bean names.
for (String name : this.interceptorNames) {
if (logger.isTraceEnabled()) {
logger.trace("Configuring advisor or advice ‘" + name + "‘");
}
if (name.endsWith(GLOBAL_SUFFIX)) {
if (!(this.beanFactory instanceof ListableBeanFactory)) {
throw new AopConfigException(
"Can only use global advisors or interceptors with a ListableBeanFactory");
}
addGlobalAdvisor((ListableBeanFactory) this.beanFactory,
name.substring(0, name.length() - GLOBAL_SUFFIX.length()));
}
else {
// If we get here, we need to add a named interceptor.
// We must check if it‘s a singleton or prototype.
Object advice;
if (this.singleton || this.beanFactory.isSingleton(name)) {
// Add the real Advisor/Advice to the chain.
advice = this.beanFactory.getBean(name);
}
else {
// It‘s a prototype Advice or Advisor: replace with a prototype.
// Avoid unnecessary creation of prototype bean just for advisor chain initialization.
advice = new PrototypePlaceholderAdvisor(name);
}
addAdvisorOnChainCreation(advice, name);
}
}
}
this.advisorChainInitialized = true;
}
生成单件代理对象
private synchronized Object getSingletonInstance() {
if (this.singletonInstance == null) {
this.targetSource = freshTargetSource();
if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
// 根据 AOP 框架判断需要代理的接口
Class<?> targetClass = getTargetClass();
if (targetClass == null) {
throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
}
//这里是设置代理对象的接口
setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
}
// Initialize the shared singleton instance.
super.setFrozen(this.freezeProxy);
//这里方法会使用ProxyFactory生成需要的Proxy
this.singletonInstance = getProxy(createAopProxy());
}
return this.singletonInstance;
}
//通过createAopProxy返回的AopProxy来得到代理对象
protected Object getProxy(AopProxy aopProxy) {
return aopProxy.getProxy(this.proxyClassLoader);
}
具体代理对象的生成,是在ProxyFactoryBean的基类AdvisedSupport的实现中借助AopProxyFactory完成。
在ProxyCreatorSupport中,AopProxy是通过AopProxyFactory生成的,需要生成的代理对象信息封装在AdvisedSupport中,这个对象也是createAopProxy的输入参数(this):
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
//通过AopProxyFactory取得AopProxy,AopProxyFactory是在初始化函数中定义的,使用的是DefaultAopProxyFactory
return getAopProxyFactory().createAopProxy(this);
}
现在问题转换为DefaultAopProxyFactory如何生成AopProxy了,这里有两种方式,JdkDynamicAopProxy和CglibProxyFactory
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
//获取配置的目标对象
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
//如果没有目标对象,抛出异常,提醒AOP应用提供正确的目标配置
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
//由于CGLIB是一个第三方类库,所以需要在CLASSPATH中配置
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
}
JdkDynamicAopProxy 生成AopProxy代理对象:
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
@Override
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);
//JdkDynamicAopProxy 需要实现InvocationHandler这里才能传this
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//...代理的回调方法,invoke
//也可以理解为拦截方法
}
}
CglibProxyFactory生成AopProxy代理对象:
@Override
public Object getProxy(ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
}
try {
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
Class<?> proxySuperClass = rootClass;
if (ClassUtils.isCglibProxyClass(rootClass)) {
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for (Class<?> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}
// Validate the class, writing log messages as necessary.
validateClassIfNecessary(proxySuperClass, classLoader);
// Configure CGLIB Enhancer...
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
enhancer.setSuperclass(proxySuperClass);
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
// fixedInterceptorMap only populated at this point, after getCallbacks call above
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
// Generate the proxy class and create a proxy instance.
return createProxyClassAndInstance(enhancer, callbacks);
}
catch (CodeGenerationException ex) {
throw new AopConfigException("Could not generate CGLIB subclass of class [" +
this.advised.getTargetClass() + "]: " +
"Common causes of this problem include using a final class or a non-visible class",
ex);
}
catch (IllegalArgumentException ex) {
throw new AopConfigException("Could not generate CGLIB subclass of class [" +
this.advised.getTargetClass() + "]: " +
"Common causes of this problem include using a final class or a non-visible class",
ex);
}
catch (Exception ex) {
// TargetSource.getTarget() failed
throw new AopConfigException("Unexpected AOP exception", ex);
}
}
拦截方法写在内部类里了(在上面getCallbacks涉及到):
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
private final AdvisedSupport advised;
public DynamicAdvisedInterceptor(AdvisedSupport advised) {
this.advised = advised;
}
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Class<?> targetClass = null;
Object target = null;
try {
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// May be null. Get as late as possible to minimize the time we
// "own" the target, in case it comes from a pool...
target = getTarget();
if (target != null) {
targetClass = target.getClass();
}
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
// Check whether we only have one InvokerInterceptor: that is,
// no real advice, but just reflective invocation of the target.
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
// We can skip creating a MethodInvocation: just invoke the target directly.
// Note that the final invoker must be an InvokerInterceptor, so we know
// it does nothing but a reflective operation on the target, and no hot
// swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = methodProxy.invoke(target, argsToUse);
}
else {
// We need to create a method invocation...
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
finally {
if (target != null) {
releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
@Override
public boolean equals(Object other) {
return (this == other ||
(other instanceof DynamicAdvisedInterceptor &&
this.advised.equals(((DynamicAdvisedInterceptor) other).advised)));
}
/**
* CGLIB uses this to drive proxy creation.
*/
@Override
public int hashCode() {
return this.advised.hashCode();
}
protected Object getTarget() throws Exception {
return this.advised.getTargetSource().getTarget();
}
protected void releaseTarget(Object target) throws Exception {
this.advised.getTargetSource().releaseTarget(target);
}
}
可以把AOP的实现部分堪称有基础设施准备和AOP运行辅助这两部分组成。
这里的AOPProxy代理对象的生成,可以看作是一个静态的AOP基础设施的建立过程。通过这个准备过程,把代理对象、拦截器这些待调用的部分都准备好,等待着AOP运行过程中对这些基础设施的使用。
对于应用触发的AOP应用,会涉及AOP框架的运行和对AOP基础设施的使用。
这些动态的运行部分,是从拦截器回调入口开始的。