Aspectj:源代码和字节码级别的编织器,用户需要使用不同于Java的新语言。
AspectWerkz:AOP框架,使用字节码动态编织器和XML配置。
JBoss-AOP:基于拦截器和元数据的AOP框架,运行在JBoss应用服务器上。以及在AOP中用到的一些相关的技术实现。
BCEL:java字节码操作类库。
Javassist:Java字节码操作类库,JBoss的一个子项目。
三种织入方式:编译期织入、类加载期织入和运行期织入。
编译期织入是指在Java编译期,采用特殊的编译器,将切面织入到Java类中;
而类加载期织入则指通过特殊的类加载器,在类字节码加载到JVM时,织入切面;
运行期织入则是采用CGLib工具或JDK动态代理进行切面的织入。
AspectJ采用编译期织入和类加载期织入的方式织入切面,是语言级的AOP实现,提供了完备的AOP支持。它用AspectJ语言定义切面,在编译期或类加载期将切面织入到Java类中。
Spring AOP的实现和其他特性的实现一样,除了可以使用Spring本身提供的AOP实现之外,还封装了业界优秀的AOP解决方案Aspectj来供应用使用。
Advice通知:
Advice定义在连接点做什么,为切面增强提供织入接口。
Advice是AOP联盟定义的一个接口,org.aopalliance.aop.Advice。
在Spring AOP实现中,使用了这个统一接口,并通过这个接口,为AOP切面增强了织入功能做了很多的细化和扩展,比如提供了更具体的通知类型,如BeforeAdvice、AfterAdvice、ThrowsAdvice等。
BeforeAdvice又演变出子接口MethodBeforeAdvice,有一个方法before,具体什么意思也不用多说。
AfterAdvice演变子接口AfterReturningAdvice,有一个方法afterReturning。
ThrowsAdvice并没有指定接口方法,但是你可以看到他继承自AfterAdvice。
Pointcut切点:
Pointcut来定义需要增强的方法的集合。
Pointcut要返回一个MethodMatcher来判断是否需要对方法调用进行增强。
其中的一个实现JdkRegexpMethodPointcut,完成了通过正则表达式完成了对方法名进行匹配的功能。
而且JdkRegexpMethodPointcut还实现了MethodMatcher接口。
JdkRegexpMethodPointcut中实现了AbstractRegexpMethodPointcut中的抽象方法matches,并用jdk的正则表达式完成匹配。
Advisor通知器:
完成对目标的切面设计Advice和关注点设计Pointcut以后,需要一个对象把他们结合起来。
DefaultPointcutAdvisor-
public DefaultPointcutAdvisor(Pointcut pointcut, Advice advice) {
this.pointcut = pointcut;
setAdvice(advice);
}
类中还有个TruePointcut的单例默认值,一直返回true。
上面提到的几个类实现都非常简单,因为,他们基本就只是属于一个“数据形式的定义”。
AOP简介
通知(Advice):通知定义了切面是什么以及何时使用。除了要描述切面要完成的工作,通知还解决了何时执行这个工作的问题。
连接点(Joinpoint):连接点是在程序执行过程中能够插入切面的一个点。这个点可以是方法被调用时、异常被抛出时、甚至字段被编辑时。切面代码可以通过这些点插入到程序的一般流程之中,从而添加新的行为。
切入点(Poincut):切入点可以缩小切面通知的连接点的范围。如果说通知定义了切面的“什么”和“何时”,那么切入点就定义了“何地”。
切面(Aspect):切面是通知和切入点的组合。
引入(Introduction):“引入”允许我们向现有的类添加新方法或者属性。
目标(Target):被通知的对象。
代理(Proxy):是向目标对象应用通知之后被创建的对象。
织入(Weaving):是把切面应用到目标对象来创建新的代理对象的过程。编译时、类加载时、运行时。
在Spring AOP实现中,使用的核心技术是动态代理。
通过JDK的动态代理特性,可以为任意Java对象创建代理对象,这个特性是通过Java Reflection API来完成的。
相反Spring AOP还将ApsectJ集成了进来。
这个代理对象可以通过使用JDK的proxy来完成,也可以通过第三方的类生成器CGLIB来完成。
接口org.springframework.beans.factory.FactoryBean<T>:
做为bean的创建的一个工厂,通过是三个方法T getObject() 、Class<?> getObjectType()、boolean isSingleton()可以看出,实现他可以作为一个bean创建的代理对象返回。
首先FactoryBean是我们的主接口,这里面的定义就是我们需要的结果,但是下面会围绕这个接口定义了一些列接口,包括资源、“算法”等操作,最终得到我们这个接口想要的东西。
----------------资源相关Aware--------------
接口org.springframework.beans.factory.Aware:
本接口没有定义任何方法,只是 作为一个超类接口存在;Marker superinterface indicating that a bean is eligible to be notified by the Spring container of a particular framework object through a callback-style method.
接口org.springframework.beans.factory.BeanFactoryAware:
继承Aware
就一个方法void setBeanFactory(BeanFactory beanFactory),定义了BeanFactory的回调注入。
接口org.springframework.beans.factory.BeanClassLoaderAware:
继承Aware
一个方法void setBeanClassLoader(ClassLoader classLoader),定义ClassLoader的回调注入。
接口org.springframework.aop.TargetClassAware:
没有继承自Aware,上面的Aware是bean相关的。这个是aop相关的。
定义一个方法Class<?> getTargetClass(),目标类获取。就是我们配置里面的<property name="target" ref="..."></property>
-----------------Advised--------------------
接口org.springframework.aop.framework.Advised:
和名字一样,Advised想干的一些资源管理。
org.springframework.aop.framework.ProxyConfig:
一些标识的存放,保证一致性。
org.springframework.aop.framework.AdvisedSupport:
Advised的实现支持类,包括对各种配置资源的管理。从调用本类的参数命名定义上AdvisedSupport config,可以知道本类就是一个资源的快照类。
org.springframework.aop.framework.ProxyCreatorSupport:
Base class for proxy factories. Provides convenient access to a configurable AopProxyFactory.
真正的创建是在AopProxy的两个是实现,对AopProxy实现的判断提供是在于AopProxyFactory,本类就是对AopProxyFactory的提供(不是AopProxyFactory的实现是提供)。
/**
* Create a new ProxyCreatorSupport instance.
*/
public ProxyCreatorSupport() {
this.aopProxyFactory = new DefaultAopProxyFactory();
}
因为本类也继承自AdvisedSupport,包含了各种所需资源。
------------------最终的创建:AopProxy---------------------
接口org.springframework.aop.framework.AopProxy:
Delegate interface for a configured AOP proxy, allowing for the creation of actual proxy objects.
两个方法Object getProxy()、Object getProxy(ClassLoader classLoader)。
AopProxy的两个重要实现Cglib2AopProxy、JdkDynamicAopProxy,也是我们最终产生AOP后的对象的地方。
接口org.springframework.aop.framework.AopProxyFactory:
整理结合需要创建AopProxy资源的地方,也是判断到底返回什么AopProxy实现类型的地方。
org.springframework.aop.framework.DefaultAopProxyFactory:
AopProxyFactory的唯一默认实现。以后我们如果想单独加入AopProxy的底层实现方式,可以从这里着手。
org.springframework.aop.framework.ProxyFactoryBean:
最终的出口
设计原理:
ProxyFactoryBean中,封装了主要代理对象的生成过程。在这个生成过程中,可以使用JDK的Proxy和CGLIB两种生成方式。
完成AOP应用的类,比如AspectJProxyFactory、ProxyFactory和ProxyFactoryBean,他们都在统一个类的继承体系下,都是ProxyConfig、AdvisedSupport和ProxyCreatorSupport的子类。
作为共同基类,可以将ProxyConfig看成是一个数据基类,这个数据基类为ProxyFactoryBean这样的子类提供了配置属性;
在另一个基类AdvisedSupport的实现中,封装了AOP对通知和通知器的相关操作,这些操作对于不同的AOP的代理对象的生成都是一样的,但对于具体的AOP代理对象的创建,AdvisedSupport把他交给他的子类们去完成;
对于ProxyCreatorSupport,可以将它看成是其子类创建AOP代理对象的一个辅助类。
使用ProxyFactoryBean:
代理(Proxy):是向目标对象应用通知之后被创建的对象
利用ProxyFactoryBean代理被切面的对象。
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xsi:schemaLocation="
- http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans.xsd
- http://www.springframework.org/schema/aop
- http://www.springframework.org/schema/aop/spring-aop.xsd">
- <bean id="audience" class="cn.partner4java.springidol.Audience"/>
- <!-- 通知(Advice):通知定义了切面是什么以及何时使用 -->
- <bean id="advice1" class="cn.partner4java.springidol.AudienceAdvice">
- <property name="audience" ref="audience"></property>
- </bean>
- <bean id="advice2" class="cn.partner4java.springidol.AudienceAroundAdvice">
- <property name="audience" ref="audience"></property>
- </bean>
- <!-- 切入点(Poincut):切入点可以缩小切面通知的连接点的范围 -->
- <bean id="performancePointcut1" class="org.springframework.aop.support.JdkRegexpMethodPointcut">
- <property name="pattern" value=".*perform"></property>
- </bean>
- <!-- 定义AspectJ方式切点 -->
- <bean id="performancePointcut2" class="org.springframework.aop.aspectj.AspectJExpressionPointcut">
- <property name="expression" value="execution(* Performer+.perform(..))"></property>
- </bean>
- <!-- 切面(Aspect):切面是通知和切入点的组合 (通知者)-->
- <bean id="audienceAdvisor1" class="org.springframework.aop.support.DefaultPointcutAdvisor">
- <property name="advice" ref="advice1"></property>
- <property name="pointcut" ref="performancePointcut1"></property>
- </bean>
- <bean id="audienceAdvisor2" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
- <property name="advice" ref="advice1"></property>
- <property name="pattern" value=".*perform"></property>
- </bean>
- <!-- 使用ProxyFactoryBean -->
- <bean id="performer" class="cn.partner4java.springidol.PerformerBean"></bean>
- <bean id="duke" class="org.springframework.aop.framework.ProxyFactoryBean">
- <property name="target" ref="performer"></property>
- <property name="interceptorNames" value="audienceAdvisor1"></property>
- <property name="proxyInterfaces" value="cn.partner4java.springidol.Performer"></property>
- </bean>
- </beans>
- 调用:
- package cn.partner4java.springidol;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class HelloWorld {
- public static void main(String[] args) {
- ApplicationContext ctx = new ClassPathXmlApplicationContext(
- "/META-INF/spring/springido.xml");
- Performer performer = (Performer) ctx.getBean("duke");
- performer.perform();
- }
- }
- ProxyFactoryBean生成AopProxy代理对象:
- /**
- * Return a proxy. Invoked when clients obtain beans from this factory bean.
- * Create an instance of the AOP proxy to be returned by this factory.
- * The instance will be cached for a singleton, and create on each call to
- * <code>getObject()</code> for a proxy.
- * @return a fresh AOP proxy reflecting the current state of this factory
- */
- 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();
- }
- }
- ProxyFactoryBean的AOP实现需要依赖JDK或者CGLIB提供的Proxy特性。
- 从FactoryBean中获取对象,是以getObject方法作为入口完成的。
- /**
- * Create the advisor (interceptor) chain. Aadvisors that are sourced
- * from a BeanFactory will be refreshed each time a new prototype instance
- * is added. Interceptors added programmatically through the factory API
- * are unaffected by such changes.
- */
- 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");
- }
- //这里是添加Advisor链的调用,是通过interceptorNames属性进行配置的
- // 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 {
- //如果程序在这里被调用,那么需要加入命名的拦截器advice,并且需要检查这个Bean是singleton还是prototype类型
- // 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;
- }
- 生成Singleton的代理对象在getSingletonInstance()的代码中完成,这个方法是ProxyFactoryBean生成AopProxy代理对象的调用入口。
- /**
- * Return the singleton instance of this class's proxy object,
- * lazily creating it if it hasn't been created already.
- * @return the shared singleton proxy
- */
- private synchronized Object getSingletonInstance() {
- if (this.singletonInstance == null) {
- this.targetSource = freshTargetSource();
- if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
- //根据AOP框架来判断需要代理的接口
- // Rely on AOP infrastructure to tell us what interfaces to proxy.
- 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;
- }
- /**
- * Return the proxy object to expose.
- * <p>The default implementation uses a <code>getProxy</code> call with
- * the factory's bean class loader. Can be overridden to specify a
- * custom class loader.
- * @param aopProxy the prepared AopProxy instance to get the proxy from
- * @return the proxy object to expose
- * @see AopProxy#getProxy(ClassLoader)
- */
- //通过createAopProxy返回的AopProxy来得到代理对象
- protected Object getProxy(AopProxy aopProxy) {
- return aopProxy.getProxy(this.proxyClassLoader);
- }
- AOP是一个接口,他由两个子类实现,Cglib2AopProxy和JdkDynamicAopProxy。
- 具体的代理对象的生成,是在ProxyFactoryBean的基类AdvisedSupport的实现中借助AopProxyFactory完成的。
- ProxyCreatorSupport:
- /**
- * Subclasses should call this to get a new AOP proxy. They should <b>not</b>
- * create an AOP proxy with <code>this</code> as an argument.
- */
- protected final synchronized AopProxy createAopProxy() {
- if (!this.active) {
- activate();
- }
- //通过AopProxyFactory取得AopProxy,这个AopProxyFactory是在初始化中定义的,默认使用的是DefaultAopProxyFactory
- return getAopProxyFactory().createAopProxy(this);
- }
- 对具体的实现层次的代理对象的生成,是由Spring封装的CglibProxyFactory和JdkDynamicAopProxy类来完成的。
- 在DefaultAopProxyFactory中创建AopProxy:
- 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.");
- }
- //如果targetClass是接口类,使用JDK来生成Proxy
- 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.");
- }
- //如果不是接口类生成Proxy,那么使用CGLIB来生成
- return CglibProxyFactory.createCglibProxy(config);
- }
- else {
- return new JdkDynamicAopProxy(config);
- }
- }
- JDK生成AopProxy代理对象:
- 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);
- }
- CGLIB生成AopProxy代理对象:
- Cglib2AopProxy--getProxy
- public Object getProxy(ClassLoader classLoader) {
- if (logger.isDebugEnabled()) {
- logger.debug("Creating CGLIB2 proxy: target source is " + this.advised.getTargetSource());
- }
- //从advised中取得在IoC容器中配置target对象
- 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);
- //验证代理对象的接口设置
- //创建并配置CGLIB的Enhancer,这个Enhancer对象是CGLIB的主要操作类
- // Configure CGLIB Enhancer...
- Enhancer enhancer = createEnhancer();
- if (classLoader != null) {
- enhancer.setClassLoader(classLoader);
- if (classLoader instanceof SmartClassLoader &&
- ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
- enhancer.setUseCache(false);
- }
- }
- //设置Enhancer对象,包括设置代理接口,回调方法
- //来自advised的IoC配置,比如使用AOP的DynamicAdvisedInterceptor拦截器
- enhancer.setSuperclass(proxySuperClass);
- enhancer.setStrategy(new UndeclaredThrowableStrategy(UndeclaredThrowableException.class));
- enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
- enhancer.setInterceptDuringConstruction(false);
- Callback[] callbacks = getCallbacks(rootClass);
- enhancer.setCallbacks(callbacks);
- enhancer.setCallbackFilter(new ProxyCallbackFilter(
- this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
- Class[] types = new Class[callbacks.length];
- for (int x = 0; x < types.length; x++) {
- types[x] = callbacks[x].getClass();
- }
- enhancer.setCallbackTypes(types);
- //通过Enhancer生成代理对象
- // Generate the proxy class and create a proxy instance.
- Object proxy;
- if (this.constructorArgs != null) {
- proxy = enhancer.create(this.constructorArgTypes, this.constructorArgs);
- }
- else {
- proxy = enhancer.create();
- }
- return proxy;
- }
- 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);
- }
- }
在这些callback回调中,对已AOP实现,是通过DynamicAdvisedInterceptor来完成的,回调入口是intercept方法。
可以把AOP的实现部分看成由基础设施设备和AOP运行辅助这两个部分组成,这里的AopProxy代理对象的生成,可以看做是一个AOP基础设施的建设过程。
通过这个准备过程,把代理对象、拦截器这些待调用的部门都准备好,等待AOP运行过程中对这些基础设施的使用。
对于应用出发AOP应用,会涉及AOP框架的运行和对AOP基础设施的使用。
这些动态的运行部分,是从前面提到的拦截器回调入口开始的,原理就是各种实现方案。
- 在Spring AOP通过JDK的Proxy方式或者CGLIB方式生成代理对象的时候,相关的拦截器已经配置到代理对象中去了,拦截器在代理对象中起作用是通过对这些方法的回调的来完成。
- 来看看AopProxy代理对象的拦截机制是怎样发挥作用和实现AOP功能的:
- JdkDynamicAopProxy的invoke拦截:
- final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable :
- /**
- * Implementation of <code>InvocationHandler.invoke</code>.
- * <p>Callers will see exactly the exception thrown by the target,
- * unless a hook method throws an exception.
- */
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- MethodInvocation invocation;
- Object oldProxy = null;
- boolean setProxyContext = false;
- TargetSource targetSource = this.advised.targetSource;
- Class targetClass = null;
- Object target = null;
- try {
- if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
- //如果目标对象没有实现Object类的基本方法:equals
- // The target does not implement the equals(Object) method itself.
- return equals(args[0]);
- }
- if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
- //如果目标对象没有实现Object类的基本方法:hashCode
- // The target does not implement the hashCode() method itself.
- return hashCode();
- }
- if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
- method.getDeclaringClass().isAssignableFrom(Advised.class)) {
- //根据代理对象的配置来调用服务
- // Service invocations on ProxyConfig with the proxy config...
- return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
- }
- Object retVal;
- 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 = targetSource.getTarget();
- if (target != null) {
- targetClass = target.getClass();
- }
- //这里获得定要好的拦截器链
- // Get the interception chain for this method.
- List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
- //如果没有设置拦截器,那么就直接调用target的对应方法
- // Check whether we have any advice. If we don't, we can fallback on direct
- // reflective invocation of the target, and avoid creating a MethodInvocation.
- if (chain.isEmpty()) {
- // 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.
- retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);
- }
- //如果有拦截器的设定,那么需要调用拦截器之后才调用目标对象的相应方法
- //通过构建一个ReflectiveMethodInvocation来实现
- else {
- // We need to create a method invocation...
- invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
- // Proceed to the joinpoint through the interceptor chain.
- retVal = invocation.proceed();
- }
- // Massage return value if necessary.
- if (retVal != null && retVal == target && method.getReturnType().isInstance(proxy) &&
- !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
- // Special case: it returned "this" and the return type of the method
- // is type-compatible. Note that we can't help if the target sets
- // a reference to itself in another returned object.
- retVal = proxy;
- }
- return retVal;
- }
- finally {
- if (target != null && !targetSource.isStatic()) {
- // Must have come from TargetSource.
- targetSource.releaseTarget(target);
- }
- if (setProxyContext) {
- // Restore old proxy.
- AopContext.setCurrentProxy(oldProxy);
- }
- }
- }
- Cglib2AopProxy的intercept拦截:
- final class Cglib2AopProxy implements AopProxy, Serializable:
- (private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable :)
- 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 <code>null</code>. 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();
- }
- //从advised中取得配置好的AOP通知
- List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
- Object retVal;
- //如果没有AOP通知配置,那么直接调用target对象的调用方法
- // 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.
- retVal = methodProxy.invoke(target, args);
- }
- else {
- //通过CglibMethodInvocation来启动advice通知
- // We need to create a method invocation...
- retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
- }
- retVal = massageReturnTypeIfNecessary(proxy, target, method, retVal);
- return retVal;
- }
- finally {
- if (target != null) {
- releaseTarget(target);
- }
- if (setProxyContext) {
- // Restore old proxy.
- AopContext.setCurrentProxy(oldProxy);
- }
- }
- }
- 目标对象方法的调用:
- 如果没有设置拦截器,那么会对目标对象的方法直接调用。对JDK方式的代理对象,是通过AopUtils.invokeJoinpointUsingReflection(target, method, args)方法实现的。
- /**
- * Invoke the given target via reflection, as part of an AOP method invocation.
- * @param target the target object
- * @param method the method to invoke
- * @param args the arguments for the method
- * @return the invocation result, if any
- * @throws Throwable if thrown by the target method
- * @throws org.springframework.aop.AopInvocationException in case of a reflection error
- */
- public static Object invokeJoinpointUsingReflection(Object target, Method method, Object[] args)
- throws Throwable {
- //这里是使用反射调用target对象方法的地方
- // Use reflection to invoke the method.
- try {
- ReflectionUtils.makeAccessible(method);
- return method.invoke(target, args);
- }
- catch (InvocationTargetException ex) {
- // Invoked method threw a checked exception.
- // We must rethrow it. The client won't see the interceptor.
- throw ex.getTargetException();
- }
- catch (IllegalArgumentException ex) {
- throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" +
- method + "] on target [" + target + "]", ex);
- }
- catch (IllegalAccessException ex) {
- throw new AopInvocationException("Could not access method [" + method + "]", ex);
- }
- }
- AOP拦截器链的调用:
- 最终AOP的拦截的处理最终都在:org.springframework.aop.framework.ReflectiveMethodInvocation--proceed()
- //在运行拦截器的拦截方法之前,需要对代理方法完成一个匹配判断,通过这个匹配判断来决定拦截器是否满足切面增强的要求。
- public Object proceed() throws Throwable {
- //从索引为-1的拦截器开始调用,并按顺序递增
- //如果拦截器链中的拦截器迭代调用完毕,这里开始调用target的函数,这个函数是通过
- //反射机制完成的,具体实现在AopUtils.invokeJoinpointUsingReflection方法中
- // 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) {
- //这里对拦截器进行动态匹配判断,这里是触发进行匹配的地方,如果和定义的Pointcut匹配,
- //那么这个advice将会得到执行
- // 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 {
- //如果不匹配,那么process会被递归调用,知道所有的拦截器都被运行过为止
- // Dynamic matching failed.
- // Skip this interceptor and invoke the next in the chain.
- return proceed();
- }
- }
- else {
- //如果是一个interceptor,直接调用这个interceptor对应的方法
- // 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);
- }
- }
- 配置通知器:
- 在整个AopProxy代理对象的回调过程中,先回到ReflectiveMethodInvocation的proceed方法。方法中有一句
- Object interceptorOrInterceptionAdvice =
- this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
- interceptorOrInterceptionAdvice是获得的拦截器,他通过拦截器机制对目标对象的行为增强器作用。
- 这个值可以先看JdkDynamicAopProxy的invoke中
- // Get the interception chain for this method.
- List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
- 知道到实现:
- AdvisedSupport
- public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class targetClass) {
- //这里使用了methodCache,一个map的cache,如果没有初始化过,会通过DefaultAdvisorChainFactory完成
- MethodCacheKey cacheKey = new MethodCacheKey(method);
- List<Object> cached = this.methodCache.get(cacheKey);
- if (cached == null) {
- cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
- this, method, targetClass);
- this.methodCache.put(cacheKey, cached);
- }
- return cached;
- }
- 取得拦截器链的工作是由配置好的advisorChainFactory来完成的,他是一个通知器连的工厂。
- 在DefaultAdvisorChainFactory实现了对通知链的获取过程,具体实现可查看源码。
- 在ProxyFactoryBean的getObject方法中对advisor进行初始化时,从XML配置中获取了advisor通知器。
- Object advice;
- //判断是单例还是prototype
- if (this.singleton || this.beanFactory.isSingleton(name)) {
- //这里是取得advice的地方,是通个beanFactory取得的,把interceptor的名字交给BeanFactory,然后通过调用getBean去获取。
- 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);
- advisor通知器的取得是委托给IoC容器完成的。
- DefaultListableBeanFactory的子类AbstractAutowireCapableBeanFactory的initializeBean初始化方法,判断了bean是否继承了BeanFactoryAware,如果是则设置回调。
- Advice通知的实现:
- 后续
本文详细解析了Spring AOP与AspectJ的实现机制,从通知、连接点、切入点、切面等方面深入阐述了面向切面编程(AOP)的核心概念与实践方法,同时结合实例演示了如何在实际项目中应用这些技术。
236

被折叠的 条评论
为什么被折叠?



