Spring Aop
来源:互联网 发布:关于网络拍卖司法解释 编辑:程序博客网 时间:2024/06/15 00:04
Spring开启AOP一般是使用@EnableAspectJAutoProxy来开启的。这个注解的主要作用是注入了一个实现了BeanPostProcessor接口的类。这个接口在前面介绍过,会嵌入到Bean的实例化过程。 所以只要我们注入这个类AnnotationAwareAspectJAutoProxyCreator也可以开启AOP功能了。完整的代码放在Github上。
@Bean public AnnotationAwareAspectJAutoProxyCreator makeAnnotationAwareAspectJAutoProxyCreator() { return new AnnotationAwareAspectJAutoProxyCreator(); }
调试AnnotationAwareAspectJAutoProxyCreator的源码会发现,这个类继承的AbstractAutoProxyCreator的方法postProcessAfterInitialization中对符合切片的bean进行了二次代理,具体的代码如下。
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (!this.earlyProxyReferences.containsKey(cacheKey)) { return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; } protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { if (beanName != null && this.targetSourcedBeans.containsKey(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; }
Aspect是通过BeanFactoryAspectJAdvisorsBuilder的buildAspectJAdvisors方法加载的。这个方法会读取bean的切片信息,并生成Advisor的列表,同时存在advisorsCache里面。
public List<Advisor> buildAspectJAdvisors() { List<String> aspectNames = null; synchronized (this) { aspectNames = this.aspectBeanNames; if (aspectNames == null) { List<Advisor> advisors = new LinkedList<Advisor>(); aspectNames = new LinkedList<String>(); String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false); for (String beanName : beanNames) { if (!isEligibleBean(beanName)) { continue; } // We must be careful not to instantiate beans eagerly as in this // case they would be cached by the Spring container but would not // have been weaved Class beanType = this.beanFactory.getType(beanName); if (beanType == null) { continue; } if (this.advisorFactory.isAspect(beanType)) { aspectNames.add(beanName); AspectMetadata amd = new AspectMetadata(beanType, beanName); if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) { MetadataAwareAspectInstanceFactory factory = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName); List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory); if (this.beanFactory.isSingleton(beanName)) { this.advisorsCache.put(beanName, classAdvisors); } else { this.aspectFactoryCache.put(beanName, factory); } advisors.addAll(classAdvisors); } else { // Per target or per this. if (this.beanFactory.isSingleton(beanName)) { throw new IllegalArgumentException("Bean with name '" + beanName + "' is a singleton, but aspect instantiation model is not singleton"); } MetadataAwareAspectInstanceFactory factory = new PrototypeAspectInstanceFactory(this.beanFactory, beanName); this.aspectFactoryCache.put(beanName, factory); advisors.addAll(this.advisorFactory.getAdvisors(factory)); } } } this.aspectBeanNames = aspectNames; return advisors; } } if (aspectNames.isEmpty()) { return Collections.EMPTY_LIST; } List<Advisor> advisors = new LinkedList<Advisor>(); for (String aspectName : aspectNames) { List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName); if (cachedAdvisors != null) { advisors.addAll(cachedAdvisors); } else { MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName); advisors.addAll(this.advisorFactory.getAdvisors(factory)); } } return advisors; }
使用的时候,Spring会根据pointCut选择合适的Advisor对相应的Bean做代理。
protected List<Advisor> findEligibleAdvisors(Class beanClass, String beanName) { List<Advisor> candidateAdvisors = findCandidateAdvisors(); List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; }
二次代理的Bean在执行的过程中是使用ReflectiveMethodInvocation的proceed方法来执行Advisor的处理逻辑的。 上一步选出来的Advisor存在interceptorsAndDynamicMethodMatchers属性里,这是一个Advisor的列表,所以执行的过程中采用了责任链模式,不同的Advisor会依次调用下一个Advisor。
public Object proceed() throws Throwable { // 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) { // 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 { // Dynamic matching failed. // Skip this interceptor and invoke the next in the chain. return proceed(); } } else { // 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); } }
这条责任链里包含了Advisor的处理顺序,通过程序的流程图能能明显的表示出来,为了完整描述,这里假设是完整的Advisor。
从图中可以完整的看出来各个Advisor的执行顺序。
自定义AOP
所以自定义AOP也是相同的思路,通过继承BeanPostProcessor来二次代理bean,完整的代码放在Github上了。 为了简便起见,只定义了一个注解@MyAspect,具体的Advisor通过函数名控制。 先看注解的定义,加上Component使Spring可以识别这个注解,并加载,pointCut属性则是定义切片。
@Target({ ElementType.TYPE })@Retention(RetentionPolicy.RUNTIME)@Documented@Componentpublic @interface MyAspect { String value() default ""; String pointCut();}
再看具体的使用上,pointCut定义了切片,然后定义了before,after,around,这三个方法,目前只实现了这三个具有代表性的Advisor。
@Configurationpublic class CustomizeAspectTest { public static void main(String[] args) { AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(); annotationConfigApplicationContext.register(CustomizeAspectTest.class); annotationConfigApplicationContext.refresh(); Test test = annotationConfigApplicationContext.getBean(Test.class); test.test(); } @Component public static class Test { public void test() { System.out.println("hello world"); } } @MyAspect(pointCut = "org.wcong.test.spring.aop.CustomizeAspectTest.Test.test") public static class MyAspectClass { void before(Object[] args) { System.out.println("aop before"); } void after(Object[] args) { System.out.println("aop after"); } void around(MethodInvocation methodInvocation, Object[] args) throws Throwable { System.out.println("aop around before"); methodInvocation.proceed(methodInvocation); System.out.println("aop around after"); } } @Bean public CustomizeAspectProxy getCustomizeAspectScan() { return new CustomizeAspectProxy(); }}
可以发现最后导出了一个CustomizeAspectProxy的类,这个就是自定义Aop的切入点了。这里面主要实现了Advisor的加载,和对符合切片的Bean的二次代理。
public class CustomizeAspectProxy implements BeanPostProcessor, ApplicationContextAware { private ApplicationContext applicationContext; private List<AbstractAdvisor> advisorList; public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { buildAdvisor(); Map<Method, List<AbstractAdvisor>> matchAdvisorMap = matchAdvisor(bean); if (matchAdvisorMap.isEmpty()) { return bean; } else { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(bean.getClass()); enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE); enhancer.setCallback(new MethodInterceptorImpl(matchAdvisorMap)); return enhancer.create(); } } private Map<Method, List<AbstractAdvisor>> matchAdvisor(Object bean) { Class<?> beanClass = bean.getClass(); Method[] methods = beanClass.getMethods(); if (methods == null) { return Collections.emptyMap(); } Map<Method, List<AbstractAdvisor>> methodListMap = new HashMap<Method, List<AbstractAdvisor>>(); for (Method method : methods) { for (AbstractAdvisor abstractAdvisor : advisorList) { if (!abstractAdvisor.isMatch(bean.getClass(), method)) { continue; } List<AbstractAdvisor> advisorList = methodListMap.get(method); if (advisorList == null) { advisorList = new LinkedList<AbstractAdvisor>(); methodListMap.put(method, advisorList); } advisorList.add(abstractAdvisor); } } return methodListMap; } private void buildAdvisor() { if (advisorList != null) { return; } synchronized (this) { if (advisorList != null) { return; } String[] beanNames = applicationContext.getBeanDefinitionNames(); advisorList = new ArrayList<AbstractAdvisor>(); for (String beanName : beanNames) { Class<?> beanClass = applicationContext.getType(beanName); MyAspect myAspect = beanClass.getAnnotation(MyAspect.class); if (myAspect == null) { continue; } Method[] methods = beanClass.getDeclaredMethods(); if (methods == null) { continue; } Object bean = applicationContext.getBean(beanName); List<AbstractAdvisor> beanAdvisorList = new ArrayList<AbstractAdvisor>(methods.length); for (Method method : methods) { if (method.getName().equals("before")) { beanAdvisorList.add(new MethodInvocation.BeforeAdvisor(bean, method)); } else if (method.getName().equals("around")) { beanAdvisorList.add(new MethodInvocation.AroundAdvisor(bean, method)); } else if (method.getName().equals("after")) { beanAdvisorList.add(new MethodInvocation.AfterAdvisor(bean, method)); } } advisorList.addAll(beanAdvisorList); } Collections.sort(advisorList, new Comparator<AbstractAdvisor>() { public int compare(AbstractAdvisor o1, AbstractAdvisor o2) { return o1.getOrder() - o2.getOrder(); } }); } } public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; }}
其中buildAdvisor是从applicationContext里面取出所有的bean选出有MyAspect注解的类,解析成Advisor,注意到后面有一个排序,是因为这个责任链是有顺序的,after>around>before。 matchAdvisor则是读取类的信息,判断需要被代理,然后返回每个方法被代理的advisorList。 接下来是实现代理的类了,这个类是cglib的一个简单的判断,发现相应的函数有Advisor,走Aop模式,没有,走普通的代理模式。
public class MethodInterceptorImpl implements MethodInterceptor { private Map<Method, List<AbstractAdvisor>> advisorMap; public MethodInterceptorImpl(Map<Method, List<AbstractAdvisor>> advisorMap) { this.advisorMap = advisorMap; } public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { List<AbstractAdvisor> advisorList = advisorMap.get(method); if (advisorList == null) { return methodProxy.invokeSuper(o, objects); } else { MethodInvocation methodInvocation = new MethodInvocation(o, method, objects, methodProxy, advisorList); return methodInvocation.proceed(methodInvocation); } }}
MethodInvocation就是具体的责任链实现的Advisor的逻辑了。MethodInvocation包含了具体需要代理的方法的元数据,并在proceed方法中开启方法的执行链路,依次调用。而这条责任链的处理链路就是after->around->before->methodProxy->around->after。
public interface Proceed { Object proceed(MethodInvocation methodInvocation) throws Throwable;}public class MethodInvocation implements Proceed { private List<AbstractAdvisor> advisorList; private Object sourceObject; private Method sourceMethod; private Object[] sourceParameters; private MethodProxy sourceMethodProxy; private int advisorIndex = -1; public MethodInvocation(Object o, Method method, Object[] objects, MethodProxy methodProxy, List<AbstractAdvisor> advisorList) { this.sourceObject = o; this.sourceMethod = method; this.sourceParameters = objects; this.sourceMethodProxy = methodProxy; this.advisorList = advisorList; } public Object proceed(MethodInvocation methodInvocation) throws Throwable { if (advisorIndex == advisorList.size() - 1) { return sourceMethodProxy.invokeSuper(sourceObject, sourceParameters); } else { advisorIndex += 1; return advisorList.get(advisorIndex).proceed(this); } } public static class AroundAdvisor extends AbstractAdvisor { public AroundAdvisor(Object aspectObject, Method aspectMethod) { super(aspectObject, aspectMethod); order = AbstractAdvisor.AROUND_ORDER; } public Object proceed(MethodInvocation methodInvocation) throws Throwable { Object[] param = { methodInvocation, methodInvocation.sourceParameters }; return aspectMethod.invoke(aspectObject, param); } } public static class BeforeAdvisor extends AbstractAdvisor { public BeforeAdvisor(Object aspectObject, Method aspectMethod) { super(aspectObject, aspectMethod); order = AbstractAdvisor.BEFORE_ORDER; } public Object proceed(MethodInvocation methodInvocation) throws Throwable { Object[] param = { methodInvocation.sourceParameters }; aspectMethod.invoke(aspectObject, param); return methodInvocation.proceed(methodInvocation); } } public static class AfterAdvisor extends AbstractAdvisor { public AfterAdvisor(Object aspectObject, Method aspectMethod) { super(aspectObject, aspectMethod); order = AbstractAdvisor.AFTER_ORDER; } public Object proceed(MethodInvocation methodInvocation) throws Throwable { methodInvocation.proceed(methodInvocation); Object[] param = { methodInvocation.sourceParameters }; return aspectMethod.invoke(aspectObject, param); } }}
结语
Spring Aop的实现主要是bean的二次代理,还是用到了BeanPostProcessor,来嵌入实现的。同时依赖了Aspectj的相关定义,通过Advisor的责任链来实现嵌入到bean方法的执行前后。同时也跟Aspectj高度耦合,会直接使用Aspectj的很多类,就很难实现定制化了。
- AOP、Spring的AOP
- AOP--Spring AOP
- Spring AOP 嵌套AOP
- spring AOP
- Spring AOP
- Spring AOP
- spring aop
- Spring AOP
- spring AOP
- spring aop
- Spring aop
- Spring-AOP
- Spring AOP
- spring aop
- spring aop
- Spring AOP
- Spring AOP
- Spring Aop
- 自定义事务
- iOS中assign、copy 、retain关键字
- 120. Triangle
- 自定义SwipeLayout--仿QQ侧滑条目
- Apache Commons工具集简介
- Spring Aop
- 使用Docker部署GitLab
- Hdu1050 Moving Tables
- Java 使用jacob ppt文件转pptx,doc转docx;word 转html、pdf等
- 搜索中台工具分享 - 来自google的经验分享
- Objective-c 学习笔记(三)
- VCS版本控制工具svn和git的小结
- less开发指南
- Android4.4-Launcher源码分析系列之Launcher介绍