spring AOP实现原理,

spring 会在初始化的时候,创建一个BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)用来为类注入切面。

AnnotationAwareAspectJAutoProxyCreator 是怎么加载到spring中的?

1. @EnableAutoConfiguration

2. AOPautoConfiguration

@Configuration
@ConditionalOnClass({ EnableAspectJAutoProxy.class, Aspect.class, Advice.class,
AnnotatedElement.class })
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration { @Configuration
@EnableAspectJAutoProxy(proxyTargetClass = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = false)
public static class JdkDynamicAutoProxyConfiguration { } @Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true)
public static class CglibAutoProxyConfiguration { } }

3. 注入的过程

    @Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
} @Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry,
@Nullable Object source) { return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}

这个类的作用:

1.拦截 advisor 类。(建议类,为bean加载切面:包括自定的advisor,和transactionAdvisor)

AbstractAutoProxyCreator.java

    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
Object cacheKey = getCacheKey(beanClass, beanName); if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}

2.拦截带有切面注解的类,和切面定义拦截的类。

    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
} // Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
} this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}

3.创建代理类

  3.1根据proxyFactory 获取对应的代理类

    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() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}

  3.2 使用proxy类,创建 proxyObject  (和cglib的用法基本一样。)

            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);

4.targetSource 的作用和原理

targetSource 是一个 被代理的对象,用来封装具体的代理对象。所有生成后的代理对象,1.调用切面,2调用targetSource.getTarget(),3.会调用method.Invoke(target,args)

用处:

1.热交换  JndiObjectTargetSource  加载spring时,tomcat先加载了dataSource,此时对已有的dataSource加切面是不和实际的。所以可以对JNDIdatasource加切面,在调用具体的方法时,由targetSource交换的通过jndi查找到的数据源。

为了兼容targetSource有了

SingletonTargetSource,EmptyTargetSource,

springAOP实现原理的更多相关文章

  1. OOP的完美点缀—AOP之SpringAOP实现原理

    OOP的完美点缀-AOP之SpringAOP实现原理 前言 OOP与AOP OOP(Object Oriented Programming,面向对象编程),通过封装.继承将程序抽象为各个层次的对象,进 ...

  2. SpringAOP实现(原理)

    AOP原理: AOP分为:JDK动态代理和CGLIB代理 静态代理:由程序员创建或特定工具自动生成源代码,再对其编译.在程序运行前,代理类的.class文件就已经存在了.              注 ...

  3. spring框架学习笔记4:SpringAOP实现原理

    AOP AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善.OOP引入 ...

  4. SpringAOP 设计原理

    1.  设计原理 引入了,代理模式. java 程序执行流: 如果从虚拟机的角度看,整个程序的过程就是方法的调用,我们按照方法的执行顺序,将方法调用成一串. 在方法之间有着Join Point 连接点 ...

  5. SpringAop实现原理及代理模式

    Spring Aop的原理 Spring的AOP就是通过动态代理实现的.当为某个Bean或者某些Bean配置切面时,Spring会为其创建代理对象,当调用该对象的某个方法时,实际是调用生成的代理类的对 ...

  6. springAOP配置原理

    什么是AOP AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善.OOP引入 ...

  7. SpringAOP 原理解析

    什么是AOP? 1: 传统的OOP编程他的代码逻辑是一种自上向下, 而在这些自上而下的过程中会产生一些横切性的问题,比如说:日志信息,权限校验认证,事务等, 2: 这些横切性问题,往往与我们的主业务逻 ...

  8. Spring知识点总结(四)之SpringAOP基础

        1. Spring aop中的基本概念        • 连接点(Joinpoint):在程序执行过程中某个特定的点,比如某方法调用的时候或者处理异常的时候.在Spring AOP中,一个连接 ...

  9. 75道阿里Java面试题,你能答上几道?

    整理了下阿里近几年的java面试题目,大家参考下吧,希望对大家有帮助,可以帮大家查漏补缺. 答对以下这些面试题,可以淘汰掉 80 % 的求职竞争者. 1.hashcode相等两个类一定相等吗?equa ...

随机推荐

  1. C++-HDU1394-Minimum Inversion Number[数据结构][树状数组]

    给出0~n-1的一个排列,可以整体移动,求逆序对最小值 把数字num[i]的加入,等价于树状数组的第n-num[i]位加1 因为num[i]是第 (n-1)-num[i]+1=n-num[i]大的数字 ...

  2. 2.9 log4j 在测试过程中打印执行日志

    Apache Log4j配置说明/log4j的分层打印    http://blog.csdn.net/zzy7075/article/details/53763728

  3. 三维数据曲面图 season绘图 panda绘图

    三维数据曲面图 season绘图 panda绘图 待办 enter description here 转化成网格坐标 season可以让绘图更美观 panda绘图可以直接根据panda数据绘制图直接p ...

  4. log设计网站,一站式一键设计log网站

    log设计网站,一站式一键设计log网站 log设计网站,一键式一站式设计log网站 待办 https://www.wix.com/buildyourwebsite5/designlogo?utm_s ...

  5. Pacemaker+ISCSI实现Apache高可用-环境准备

    Pacemaker是红帽7上的集群管理器,用于替代6上RHCS 配置ISCSI 服务端 yum -y install targetcli systemctl enable target.service ...

  6. Linux - shell - xargs - 基础

    概述 简述 xargs 的使用 背景 尝试批量操作文件 发现一些问题小问题 然后, 尝试解决 准备 环境 OS centos7 1. 操作: 尝试创建多个 文本文件 概述 尝试创建多个文本文件 1. ...

  7. centos7 sshpass 用法详解

    可以参考文章:https://www.cnblogs.com/kaishirenshi/p/7921308.html 安装方式直接通过yum 安装 yum -y install sshpass 常用的 ...

  8. ES5中, map 和 forEach的区别

    forEach和map区别在哪里知道吗? // forEach Array.prototype.forEach(callback(item, index, thisArr), thisArg) // ...

  9. Apollo安装教程

    最近一直在研究Apollo的安装问题,浪费了几天时间,所有特意来记录一下安装心得. UBUNTU 14.04安装 这个我是把自己的笔记本全部转换为ubuntu系统,操作相对简单,大家可以自行查找,另外 ...

  10. 【代码总结】Struts2 Action接受参数方式的对比

    一.属性方式 1.Action中:对应表单参数的setter.getter 2.页面中  :Form中元素name取值属性名 <s:property value="属性名" ...