这几天开发环境换成了Ubuntu,花了很长的时间,从今天开始准备学习Spring AOP相关的部分.
我们知道<aop:aspectj-autoproxy/>在配置文件中配置了,就会支持aop的注解开发
registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
我们从这个代码,进入到AOP的研究之中,当我们遇到了aspectj-autoproxy,这个时候就对应着注册了AspectJAutoProxyBeanDefinitionParser(),然后我们就研究一下这个类.(在解析配置文件之后,一旦遇到了aspectj-autoproxy,就会调用AspectJAutoProxyBeanDefinitionParser),然后我们进入到,这个类中
public BeanDefinition parse(Element element, ParserContext parserContext) {
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
extendBeanDefinition(element, parserContext);
return null;
}
其中最重要的就是第一句代码registerAspectJAnnotationAutoProxyCreatorIfNecessary,然后我们进入到这个之中
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
这个时候就出现了,第一个重要的类AnnotationAwareAspectJAutoProxyCreator.在解析xml文件中,读取到了aspectj-autoproxy,然后就会注册或者升级AnnotationAwareAspectJAutoProxyCreator,这个类的作用大概就是书中说的.
AOP的实现都是通过AnnotationAwareAspectJAutoProxyCreator来实现的,它会根据@Point定义的切点来来自动代理相匹配的bean
按我自己的理解,AnnotationAwareAspectJAutoProxyCreator这个类的作用就是根据注解的切点表达式来自动代理匹配上的bean.
这是第一个需要注意的点,我们回到解析自定义标签的核心代码位置
public static void registerAspectJAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
registerComponentIfNecessary(beanDefinition, parserContext);
}
我们已经实现了第一步,也就是以上代码中的第一步,注册或者升级AnnotationAwareAspectJAutoProxyCreator.有了这个类就可以通过注解的切点表达式来生成代理类.
然后我们看一下第二段代码
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
处理proxy-target-class以及expose-proxy属性.然后我们来理解一下这两个属性
proxy-target-class:Spring Aop部分使用JDK动态代理或者cglib代理来为对象创建代理.(尽量使用JDK的动态代理).如果一个对象实现了至少一个借口,此时就会使用JDK动态代理.若对象中没有实现任何的接口,此时就会使用cglib代理.使用cglib代理需要考虑两种情况
无法通知final方法,因为这种方法不能被复写.
你需要讲cglib二进制发型包放在classpath下面.
强制使用cglib代理需要将<aop:config>的proxy-target-class属性设为true.
我们来看一下jdk动态代理和cglib代理的区别:
JDK动态代理:代理的对象必须是某个接口的实现,它是通过在运行期间创建一个接口的实现类完成对目标对象的代理.
cglib代理:针对的是运行期间扩展的子类.它底层是依靠ASM操作字节码实现的,性能比jdk要强.
然后我们来学习一个expose-proxy的作用:
有时候目标对象的内部的自我调用无法实施切面的增强:
public interface A
{
public void A();public void B();
}
@Service
public interface Aimp implements AService
{
@Transactional(.....)
public void a()
{ this.b();
}
@Transactional(.....)
public void b()
{ System.out.println("");
}
}
这种情况下,b下的增强就不会起作用,这个时候要将expose-proxy设为true,然后b修改为
截图的形式,就可以实现代理的创建了.
这个时候,为AOP的准备工作就完成了,然后我们要研究的就是如何创建一个增强了.