AdvisorAdapter
spring aop框架对BeforeAdvice、AfterAdvice、ThrowsAdvice三种通知类型的支持实际上是借助适配器模式来实现的,这样的好处是使得框架允许用户向框架中加入自己想要支持的任何一种通知类型
的AdvisorAdapter是一个适配器接口,它定义了自己支持的Advice类型,并且能把一个Advisor适配成MethodInterceptor(这也是AOP联盟定义的借口),以下是它的定义
public interface AdvisorAdapter { // 判断此适配器是否支持特定的Advice boolean supportsAdvice(Advice advice); // 将一个Advisor适配成MethodInterceptor MethodInterceptor getInterceptor(Advisor advisor); }
一般我们自己并不需要自己去提供此接口的实现(除非你还行适配被的Advice进来),因为Spring为我们提供了对应的实现:
实现也非常的简单,如下:
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable { @Override public boolean supportsAdvice(Advice advice) { return (advice instanceof MethodBeforeAdvice); } @Override public MethodInterceptor getInterceptor(Advisor advisor) { MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice(); return new MethodBeforeAdviceInterceptor(advice); } } // 都转为了AOP联盟的MethodInterceptor 从而实现拦截统一的拦截工作 public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable { private MethodBeforeAdvice advice; /** * Create a new MethodBeforeAdviceInterceptor for the given advice. * @param advice the MethodBeforeAdvice to wrap */ public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) { Assert.notNull(advice, "Advice must not be null"); this.advice = advice; } @Override public Object invoke(MethodInvocation mi) throws Throwable { this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis()); // 最终调用,实现了链式调用的效果 return mi.proceed(); } }
参考:AdvisorAdapterRegistry和DefaultAdvisorAdapterRegistry,GlobalAdvisorAdapterRegistry用于管理管理AdvisorAdapter的
如果我们想把自己定义的AdvisorAdapter注册到spring aop框架中,怎么办?
- 把我们自己写好得AdvisorAdapter放进Spring IoC容器中
- 配置一个AdvisorAdapterRegistrationManager,它是一个BeanPostProcessor,它会检测所有的Bean。若是AdvisorAdapter类型,就:this.advisorAdapterRegistry.registerAdvisorAdapter((AdvisorAdapter) bean);
TargetSource
该接口代表一个目标对象,在aop调用目标对象的时候,使用该接口返回真实的对象。
比如它有其中两个实现SingletonTargetSource和PrototypeTargetSource代表着每次调用返回同一个实例,和每次调用返回一个新的实例
TargetClassAware
所有的Aop代理对象或者代理工厂(proxy factory)都要实现的接口,该接口用于暴露出被代理目标对象类型;
public interface TargetClassAware { // 返回被代理得目标类型 AopUtils#getTargetClass(Object) @Nullable Class<?> getTargetClass(); }
AspectMetadata
:Metadata for an AspectJ aspect class
表示一个切面的元数据类。
public class AspectMetadata implements Serializable { private final String aspectName; private final Class<?> aspectClass; // AjType这个字段非常的关键,它表示有非常非常多得关于这个切面的一些数据、方法(位于org.aspectj下) private transient AjType<?> ajType; // 解析切入点表达式用的,但是真正的解析工作为委托给`org.aspectj.weaver.tools.PointcutExpression`来解析的 //若是单例:则是Pointcut.TRUE 否则为AspectJExpressionPointcut private final Pointcut perClausePointcut; public AspectMetadata(Class<?> aspectClass, String aspectName) { this.aspectName = aspectName; Class<?> currClass = aspectClass; AjType<?> ajType = null; // 此处会一直遍历到顶层知道Object 直到找到有一个是Aspect切面就行,然后保存起来 // 因此我们的切面写在父类上 也是欧克的 while (currClass != Object.class) { AjType<?> ajTypeToCheck = AjTypeSystem.getAjType(currClass); if (ajTypeToCheck.isAspect()) { ajType = ajTypeToCheck; break; } currClass = currClass.getSuperclass(); } // 由此可见,我们传进来的Class必须是个切面或者切面的子类的~~~ if (ajType == null) { throw new IllegalArgumentException("Class '" + aspectClass.getName() + "' is not an @AspectJ aspect"); } // 显然Spring AOP目前也不支持优先级的声明。。。 if (ajType.getDeclarePrecedence().length > 0) { throw new IllegalArgumentException("DeclarePrecendence not presently supported in Spring AOP"); } this.aspectClass = ajType.getJavaClass(); this.ajType = ajType; // 切面的处在类型:PerClauseKind 由此可议看出,Spring的AOP目前只支持下面4种 switch (this.ajType.getPerClause().getKind()) { case SINGLETON: // 如国是单例,这个表达式返回这个常量 this.perClausePointcut = Pointcut.TRUE; return; case PERTARGET: case PERTHIS: // PERTARGET和PERTHIS处理方式一样 返回的是AspectJExpressionPointcut AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut(); ajexp.setLocation(aspectClass.getName()); //设置好 切点表达式 ajexp.setExpression(findPerClause(aspectClass)); ajexp.setPointcutDeclarationScope(aspectClass); this.perClausePointcut = ajexp; return; case PERTYPEWITHIN: // Works with a type pattern // 组成的、合成得切点表达式~~~ this.perClausePointcut = new ComposablePointcut(new TypePatternClassFilter(findPerClause(aspectClass))); return; default: // 其余的Spring AOP暂时不支持 throw new AopConfigException( "PerClause " + ajType.getPerClause().getKind() + " not supported by Spring AOP for " + aspectClass); } } private String findPerClause(Class<?> aspectClass) { String str = aspectClass.getAnnotation(Aspect.class).value(); str = str.substring(str.indexOf('(') + 1); str = str.substring(0, str.length() - 1); return str; } ... public Pointcut getPerClausePointcut() { return this.perClausePointcut; } // 判断perThis或者perTarger,最单实例、多实例处理 public boolean isPerThisOrPerTarget() { PerClauseKind kind = getAjType().getPerClause().getKind(); return (kind == PerClauseKind.PERTARGET || kind == PerClauseKind.PERTHIS); } // 是否是within的 public boolean isPerTypeWithin() { PerClauseKind kind = getAjType().getPerClause().getKind(); return (kind == PerClauseKind.PERTYPEWITHIN); } // 只要不是单例的,就都属于Lazy懒加载,延迟实例化的类型~~~~ public boolean isLazilyInstantiated() { return (isPerThisOrPerTarget() || isPerTypeWithin()); } }
Spring AOP切面实例化模型
Spring AOP支持AspectJ的singleton、perthis、pertarget、pertypewithin实例化模型(目前不支持percflow、percflowbelow) 参见枚举类PerClauseKind
- singleton:即切面只会有一个实例;
- perthis:每个切入点表达式匹配的连接点对应的AOP对象(代理对象)都会创建一个新切面实例;
- pertarget:每个切入点表达式匹配的连接点对应的目标对象都会创建一个新的切面实例
- pertypewithin:
默认是singleton实例化模型,Schema风格只支持singleton实例化模型,而@AspectJ风格支持这三种实例化模型
singleton:使用@Aspect()指定,即默认就是单例实例化模式,在此就不演示示例了
perthis:每个切入点表达式匹配的连接点对应的AOP代理对象都会创建一个新的切面实例,使用@Aspect("perthis(切入点表达式)")指定切入点表达式;
// 他将为每个被切入点表达式匹配上的代理对象,都创建一个新的切面实例(此处允许HelloService是接口) @Aspect("perthis(this(com.fsx.HelloService))")
pertarget:每个切入点表达式匹配的连接点对应的目标对象都会创建一个新的切面实例,使用@Aspect("pertarget(切入点表达式)")指定切入点表达式; 此处要求HelloService不能是接口
另外需要注意一点:若在Spring内要使用perthis和pertarget,请把切面的Scope定义为:prototype
AspectInstanceFactory
:切面工厂
专门为切面创建实例的工厂(因为切面也不一定是单例的,也支持各种多例形式。上面已有说明)
// 它实现了Order接口哦~~~~支持排序的 public interface AspectInstanceFactory extends Ordered { //Create an instance of this factory's aspect. Object getAspectInstance(); //Expose the aspect class loader that this factory uses. @Nullable ClassLoader getAspectClassLoader(); }
它的实现类如下:
SimpleAspectInstanceFactory:根据切面的aspectClass,调用空构造函数反射.newInstance()创建一个实例(备注:构造函数private的也没有关系)
SingletonAspectInstanceFactory:这个就更简单了,因为已经持有aspectInstance得引用了,直接return即可
MetadataAwareAspectInstanceFactory
AspectInstanceFactory的子接口。提供了获取AspectMetadata的方法
public interface MetadataAwareAspectInstanceFactory extends AspectInstanceFactory { AspectMetadata getAspectMetadata(); // Spring4.3提供 和beanFactory.getSingletonMutex() 否则一般都是this Object getAspectCreationMutex(); }
SimpleMetadataAwareAspectInstanceFactory和SingletonMetadataAwareAspectInstanceFactory已经直接关联到AspectMetadata,所以直接return即可。
LazySingletonAspectInstanceFactoryDecorator也只是个简单的装饰而已。
BeanFactoryAspectInstanceFactory
:
这个就和Bean工厂有关了。比较重要
public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInstanceFactory, Serializable { // 持有对Bean工厂的引用 private final BeanFactory beanFactory; // 需要处理的名称 private final String name; private final AspectMetadata aspectMetadata; // 传了Name,type可议不传,内部判断出来 public BeanFactoryAspectInstanceFactory(BeanFactory beanFactory, String name) { this(beanFactory, name, null); } public BeanFactoryAspectInstanceFactory(BeanFactory beanFactory, String name, @Nullable Class<?> type) { this.beanFactory = beanFactory; this.name = name; Class<?> resolvedType = type; // 若没传type,就去Bean工厂里看看它的Type是啥 type不能为null~~~~ if (type == null) { resolvedType = beanFactory.getType(name); Assert.notNull(resolvedType, "Unresolvable bean type - explicitly specify the aspect class"); } // 包装成切面元数据类 this.aspectMetadata = new AspectMetadata(resolvedType, name); } // 此处:切面实例 是从Bean工厂里获取的 需要注意 // 若是多例的,请注意Scope的值 @Override public Object getAspectInstance() { return this.beanFactory.getBean(this.name); } @Override @Nullable public ClassLoader getAspectClassLoader() { return (this.beanFactory instanceof ConfigurableBeanFactory ? ((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader() : ClassUtils.getDefaultClassLoader()); } @Override public AspectMetadata getAspectMetadata() { return this.aspectMetadata; } @Override @Nullable public Object getAspectCreationMutex() { if (this.beanFactory.isSingleton(this.name)) { // Rely on singleton semantics provided by the factory -> no local lock. return null; } else if (this.beanFactory instanceof ConfigurableBeanFactory) { // No singleton guarantees from the factory -> let's lock locally but // reuse the factory's singleton lock, just in case a lazy dependency // of our advice bean happens to trigger the singleton lock implicitly... return ((ConfigurableBeanFactory) this.beanFactory).getSingletonMutex(); } else { return this; } } @Override public int getOrder() { Class<?> type = this.beanFactory.getType(this.name); if (type != null) { if (Ordered.class.isAssignableFrom(type) && this.beanFactory.isSingleton(this.name)) { return ((Ordered) this.beanFactory.getBean(this.name)).getOrder(); } // 若没实现接口,就拿注解的值 return OrderUtils.getOrder(type, Ordered.LOWEST_PRECEDENCE); } return Ordered.LOWEST_PRECEDENCE; } }
PrototypeAspectInstanceFactory:多例专用的工厂 若是多例的,推荐使用
public class PrototypeAspectInstanceFactory extends BeanFactoryAspectInstanceFactory implements Serializable { public PrototypeAspectInstanceFactory(BeanFactory beanFactory, String name) { super(beanFactory, name); // 若是单例,直接报错了 if (!beanFactory.isPrototype(name)) { throw new IllegalArgumentException( "Cannot use PrototypeAspectInstanceFactory with bean named '" + name + "': not a prototype"); } } }
下面介绍下aspectj这个jar包下几个重要的类