aop自定义配置
aop利用了spring的自定义标签
http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler
在bean的配置文件中只要找到了aop命名空间对应的标签,就会通过AopNamespaceHandler进行解析。
@Overridepublic void init() {// In 2.0 XSD as well as in 2.5+ XSDsregisterBeanDefinitionParser("config", new ConfigBeanDefinitionParser());registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());// Only in 2.0 XSD: moved to context namespace in 2.5+registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());}
aop注册beanPostProcessor
重点来分析一下AspectJAutoProxyBeanDefinitionParser
public BeanDefinition parse(Element element, ParserContext parserContext) {AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);extendBeanDefinition(element, parserContext);return null;}
// 主要是注册了这个AnnotationAwareAspectJAutoProxyCreator bean定义public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);}
AnnotationAwareAspectJAutoProxyCreator这个类实现了InstantiationAwareBeanPostProcessor这个接口。按照前文描述的扩展点来说会在bean的实例化周期按照次序调用其具体的方法。主要关注一下postProcessAfterInitialization。 aop就是利用了这个方法,在获取到原对象之后对其进行增强。
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (bean != null) {Object cacheKey = getCacheKey(bean.getClass(), beanName);if (this.earlyProxyReferences.remove(cacheKey) != bean) {return wrapIfNecessary(bean, beanName, cacheKey);}}return bean;}
简短总结:
aop生效的原理
配置了aop,就会让其注册AnnotationAwareAspectJAutoProxyCreator这个bean定义,其本质利用了spring的扩展点,让每一个bean初始化之后都会调用postProcessAfterInitialization方法,从而返回生成的新的代理对象
aop的postProcess方法
在上述描述中已经知道为什么aop会生效了,其postProcessAfterInitialization方法也就是生成代理的方法,其实生成代理的方法也很好描述,就是找到哪个对象需要代理,代理之后的方法如何实现。
aop中三个概念
Advice
Advice 就是你想要添加到现有代码中的额外逻辑。
Pointcut
决定了“哪里”应用 Advice
Advisor
可以看作是一个将 Advice 与 Pointcut 结合起来的概念
找到advisor
java">// 找到合适的advisor的外层方法
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {// 找到所有的advisorList<Advisor> candidateAdvisors = findCandidateAdvisors();// 找到当前bean对应的advisorList<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);extendAdvisors(eligibleAdvisors);if (!eligibleAdvisors.isEmpty()) {eligibleAdvisors = sortAdvisors(eligibleAdvisors);}return eligibleAdvisors;}
java">// 找到所有的advisorprotected List<Advisor> findCandidateAdvisors() {// 找到实现了advisor接口的对象List<Advisor> advisors = super.findCandidateAdvisors();// 找到所有被aspect标记的对象advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());return advisors;}
java">// 找到注册到bean工厂定义的所有Advisor
public List<Advisor> findAdvisorBeans() {String[] advisorNames = this.cachedAdvisorBeanNames;advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Advisor.class, true, false);for (String name : advisorNames) {List<Advisor> advisors = new ArrayList<Advisor>();advisors.add(this.beanFactory.getBean(name, Advisor.class));}}
java">// 这个是pointcutAdvisor类型的根据当前类匹配advisor的方法
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {if (!pc.getClassFilter().matches(targetClass)) {return false;}MethodMatcher methodMatcher = pc.getMethodMatcher();if (methodMatcher == MethodMatcher.TRUE) {// No need to iterate the methods if we're matching any method anyway...return true;}Set<Class<?>> classes = new LinkedHashSet<Class<?>>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));classes.add(targetClass);for (Class<?> clazz : classes) {Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);for (Method method : methods) {if ((introductionAwareMethodMatcher != null &&introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||methodMatcher.matches(method, targetClass)) {return true;}}}return false;}
代理增强
代理增强有两种方案
一种是基于接口的jdk动态代理、而是基于当前类为父类的cglib动态代理。默认是jdk动态代理,但是如果在aop配置中指定了traget-class,则会默认使用cglib
入口:org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createProxy
java">// 生成动态代理工厂,然后去获取代理类
protected Object createProxy(Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {if (this.beanFactory instanceof ConfigurableListableBeanFactory) {AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);}ProxyFactory proxyFactory = new ProxyFactory();proxyFactory.copyFrom(this);if (!proxyFactory.isProxyTargetClass()) {if (shouldProxyTargetClass(beanClass, beanName)) {proxyFactory.setProxyTargetClass(true);}else {evaluateProxyInterfaces(beanClass, proxyFactory);}}Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);proxyFactory.addAdvisors(advisors);proxyFactory.setTargetSource(targetSource);return proxyFactory.getProxy(getProxyClassLoader());}
接下来以jdk动态代理为例,看看其是怎么生成代理的,jdk动态代理主要是要实现InvocationHandler接口,然后在调用方法的时候会调用到其invoke方法
java">public Object getProxy(ClassLoader classLoader) {// 找到合适的代理的父接口,然后生成代理Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);}
java"> @Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 构建切面的拦截器链List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);// 通过构造的拦截器链进行方法调用retVal = invocation.proceed();}
通过切面构造拦截器链的过程。主要两种方式
1、通过注册到AdvisorAdapterRegistry
2、advisor本身实现了MethodInterceptor接口
java">AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);public MethodInterceptor[] getInterceptors(Advisor advisor) {List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(3);Advice advice = advisor.getAdvice();// 自身实现了MethodInterceptor接口if (advice instanceof MethodInterceptor) {interceptors.add((MethodInterceptor) advice);}// 通过注册上来的适配器,转换成对应的interceptorfor (AdvisorAdapter adapter : this.adapters) {if (adapter.supportsAdvice(advice)) {interceptors.add(adapter.getInterceptor(advisor));}}if (interceptors.isEmpty()) {throw new UnknownAdviceTypeException(advisor.getAdvice());}return interceptors.toArray(new MethodInterceptor[interceptors.size()]);}// 默认注册上来的interceptor
public DefaultAdvisorAdapterRegistry() {registerAdvisorAdapter(new MethodBeforeAdviceAdapter());registerAdvisorAdapter(new AfterReturningAdviceAdapter());registerAdvisorAdapter(new ThrowsAdviceAdapter());}
链式调用interceptor方法
java">invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
retVal = invocation.proceed();public Object proceed() throws Throwable {// 调用链执行完了之后,执行被代理对象的方法if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {return invokeJoinpoint();}// 获取下一个执行的拦截器Object interceptorOrInterceptionAdvice =this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);// 执行下一个拦截器的invoke方法return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);}
}