Spring基于注解形式的 AOP的原理流程及源码解析(一)
2017-11-06 10:02
871 查看
在Spring的配置类上添加注解@EnableAspectJAutoProxy:
Spring在解析此类时,会解析类上的所有注解,如果这个注解是一个合成注解,合成的注解元素中含有Spring内有特殊作用的注解,则会递归的解析。
EnableAspectJAutoProxy 的元注解中含有@Import注解,此注解在Spring容器中负责引入一个类,此类若是一个普通的类,则当做一个Bean,和@ComponentScan扫描注解生成的Bean一样;若是一个ImportSelecter,则从几个类中筛选出一个类,返回其全名,到时候生成此Bean;若引入的是一个ImportBeanDefinitionRegistrar的实现类,则能够手动根据注解的信息注册BeanDefinition,到时候生成Bean。
@EnableAspectJAutoProxy 的元注解中含有@Import,引入了一个ImportBeanDefinitionRegistrar的实现类AspectJAutoProxyRegistrar:
AspectJAutoProxyRegistrar 根据注解@EnableAspectJAutoProxy上的属性来注册相应的Bean,proxyTargetClass = true 指定使用CGLIB来作为AOP的代理实现方式。若不设置此属性,则默认使用jdk proxy作为代理实现方式。他们两者的区别是: jdk动态代理只支持接口的方法代理,不支持类自身的方法,它动态地生成一个代理类,继承自Proxy,实现被代理的接口,内部持有被代理对象;而CGLIB则支持所有的方法代理,它动态生成一个代理类,继承自被代理类,所以叫TargetClass。
@Configuration @EnableAspectJAutoProxy(proxyTargetClass = true) public class MvcContextConfig extends WebMvcConfigurerAdapter { }
Spring在解析此类时,会解析类上的所有注解,如果这个注解是一个合成注解,合成的注解元素中含有Spring内有特殊作用的注解,则会递归的解析。
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(AspectJAutoProxyRegistrar.class) public @interface EnableAspectJAutoProxy { /** * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed * to standard Java interface-based proxies. The default is {@code false}. */ boolean proxyTargetClass() default false; /** * Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal} * for retrieval via the {@link org.springframework.aop.framework.AopContext} class. * Off by default, i.e. no guarantees that {@code AopContext} access will work. * @since 4.3.1 */ boolean exposeProxy() default false; }
EnableAspectJAutoProxy 的元注解中含有@Import注解,此注解在Spring容器中负责引入一个类,此类若是一个普通的类,则当做一个Bean,和@ComponentScan扫描注解生成的Bean一样;若是一个ImportSelecter,则从几个类中筛选出一个类,返回其全名,到时候生成此Bean;若引入的是一个ImportBeanDefinitionRegistrar的实现类,则能够手动根据注解的信息注册BeanDefinition,到时候生成Bean。
@EnableAspectJAutoProxy 的元注解中含有@Import,引入了一个ImportBeanDefinitionRegistrar的实现类AspectJAutoProxyRegistrar:
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar { /** * Register, escalate, and configure the AspectJ auto proxy creator based on the value * of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing * {@code @Configuration} class. */ @Override public void registerBeanDefinitions( AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry); //注册一个AOP代理实现的Bean AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class); if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) { AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); } if (enableAspectJAutoProxy.getBoolean("exposeProxy")) { AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry); } } }
AspectJAutoProxyRegistrar 根据注解@EnableAspectJAutoProxy上的属性来注册相应的Bean,proxyTargetClass = true 指定使用CGLIB来作为AOP的代理实现方式。若不设置此属性,则默认使用jdk proxy作为代理实现方式。他们两者的区别是: jdk动态代理只支持接口的方法代理,不支持类自身的方法,它动态地生成一个代理类,继承自Proxy,实现被代理的接口,内部持有被代理对象;而CGLIB则支持所有的方法代理,它动态生成一个代理类,继承自被代理类,所以叫TargetClass。
public abstract class AopConfigUtils { //有三种AOP的配置形式,有基于Spring内置的,有基于用户配置文件的,有基于注解的,基于注解的优先级最高, //一般配置一种就可以,如果配置多种则优先级高的会覆盖优先级低的 static { APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class); APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class); APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class); } public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) { return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null); } //注册AnnotationAwareAspectJAutoProxyCreator到容器中,此类负责基于注解的AOP动态代理实现 public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) { return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source); } //设置支持类的代理,设置此属性到时候会使用CGLIB来生成动态代理类 public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) { if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME); definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE); } } private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) { Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME); 4000 if (!cls.getName().equals(apcDefinition.getBeanClassName())) { int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName()); int requiredPriority = findPriorityForClass(cls); //通过比较代理类在集合中的序号来确定优先级,基于注解形式的优先级高 if (currentPriority < requiredPriority) { apcDefinition.setBeanClassName(cls.getName()); } } return null; } RootBeanDefinition beanDefinition = new RootBeanDefinition(cls); beanDefinition.setSource(source); beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE); beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition); return beanDefinition; } }
相关文章推荐
- Spring基于注解形式的 AOP的原理流程及源码解析(二)
- Spring基于注解形式的 AOP的原理流程及源码解析(三)
- Spring基于注解形式的 AOP的原理流程及源码解析(四)
- Spring源码解析-基于注解依赖注入
- spring AOP 源码解析 及其实现原理
- Spring核心框架 - AOP的原理及源码解析
- Spring IOC和Spring AOP的实现原理(源码主线流程)
- Spring AOP源码解析——AOP动态代理原理和实现方式
- Spring源码解析之四 ------ AOP原理和源码分析
- Spring核心框架 - AOP的原理及源码解析
- Spring IOC和Spring AOP的实现原理(源码主线流程)
- Spring IOC和Spring AOP的实现原理(源码主线流程)
- Spring IOC和Spring AOP的实现原理(源码主线流程)
- 深入剖析Spring Web源码(九) - 处理器映射,处理器适配器以及处理器的实现 - 基于注解控制器流程的实现
- (八)Spring核心框架 - AOP的原理及源码解析
- spring源码解析-AOP原理
- 基于注解的Spring AOP的配置和使用--转载
- Spring对注解(Annotation)处理源码分析2——解析和注入注解配置的资源
- 基于Spring aop 和JAVA注解方式添加日志
- spring源码剖析(六)AOP实现原理剖析