- AOP的概念
- 浏览: 112138 次
- 性别:
- 来自: 广州
文章分类
最新评论
spring4.0源码分析━━━(AOP实现)
- 博客分类:
- spring
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程(也叫面向方面)。这就让一些问题很简单化了,例如:开始我们实现了一些逻辑并上线了,现在客户又来了一个新的需求。要在每次交易之前统计下,或者记录下他们的交易简单资料。而你发现你其他模块可能正好有这部分的功能。那AOP就可以用得上了,使用AOP就可以在不修改源代码的情况下新增这些功能。就是在交易前这个切面,新装你的一些功能。这有点像拦截器和Filter。其实都是一个原理。前面说了解析xml和Bean的实例化。
而AOP的实现的话都是在我前面两篇spring3.0源码分析的基础上实现。其实AOP算是对自己本身IOC的实例,你学好弄懂AOP。基本IOC的也是懂了。但是这里的AOP也用到了一些新的东西,像Aspect,还有JVM的反射和动态代理。还有CGLIB这里也是有用到的。但是默认的实现是用JVM的动态代理。
- AOP的实例
AOP用起来还是很简单的。就把xml配置好就算完工了。有Advisor和aspect两种方式来完成。如果是用Advisor的话需要实现AfterReturningAdvice,MethodBeforeAdvice,ThrowsAdvice等接口。而如果用aspect的话则不用继承或者实现其他的类,一个普通的类即可。
public class LogAop { private final static Log log = LogFactory.getLog(LogAop.class); public void addLog(){ log.info("add log ========================"); } }
public class BeforeAdvisor implements MethodBeforeAdvice { private final static Log log =LogFactory.getLog(BeforeAdvisor.class); private int testSEL; @Override public void before(Method method, Object[] args, Object target) throws Throwable { log.info("in before advice and method="+method.getName()+ " args "+args.length); } ..........
public class AfterAdvisor implements AfterReturningAdvice { private final static Log log =LogFactory.getLog(AfterAdvisor.class); ........ @Override public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { // TODO Auto-generated method stub log.info("test sel the testSEL "+testSEL); log.info("after return advice"); } }
而配置文件如下:
<bean id="LogAop" class="com.zzx.study.aop.LogAop" /> <bean id="beforeAdvisor" class="com.zzx.study.aop.BeforeAdvisor" > <property name="testSEL" value="11"/> </bean> <bean id="beforeAdvisor2" class="com.zzx.study.aop.BeforeAdvisor2" > <property name="testSEL" value="23"/> </bean> <bean id="afterAdvisor" class="com.zzx.study.aop.AfterAdvisor" > <property name="testSEL" value="11"/> </bean> <aop:config> <aop:pointcut expression="execution(* com.zzx.study.di.BankSecurityDaoImpl.add(..))" id="target" /> <aop:pointcut expression="execution(* com.zzx.study.di.Ban*.ad*(..))" id="nonePointCutTest" /> <aop:advisor id="bid" pointcut-ref="target" advice-ref="beforeAdvisor" /> <aop:advisor id="noAdvisor" pointcut-ref="nonePointCutTest" advice-ref="beforeAdvisor2" /> <aop:advisor id="aid" pointcut-ref="target" advice-ref="afterAdvisor" /> <aop:aspect ref="LogAop" > <aop:after method="addLog" pointcut-ref="target"/> </aop:aspect> </aop:config>
向上面实现后则如果执行BankSecurityDaoImpl的add方法前就会执行BeforeAdvisor的before方法,然后执行add方法,最后是LogAop的addLog方法,AfterAdvisor的afterReturning方法。这里还可以让Advisor实现Order定义这些执行的前后。
public class BeforeAdvisor implements MethodBeforeAdvice,Ordered { ............ @Override public int getOrder() { // TODO Auto-generated method stub return 2; } }
这里的有一个getOrder方法,返回int值,越小则越先执行。
- AOP在spring中的实现
在解析xml的时候说过,如果发现不是bean标签,则会是不同的类来解析。解析aop的为http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler。也就是AopNamespaceHandler类。进去到AopNamespaceHandler类中parse方法,实际是调用其父类的NamespaceHandlerSupport的parse方法。
private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) { String localName = parserContext.getDelegate().getLocalName(element); BeanDefinitionParser parser = this.parsers.get(localName); if (parser == null) { parserContext.getReaderContext().fatal( "Cannot locate BeanDefinitionParser for element [" + localName + "]", element); } return parser; }
这里的parses是在解析xml的时候初始化。
public void init() { // In 2.0 XSD as well as in 2.1 XSD. registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser()); registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser()); registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator()); // Only in 2.0 XSD: moved to context namespace as of 2.1 registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser()); }
如果是config标签,则是用ConfigBeanDefinitionParser类了,如果是aspectj-autoproxy标签则是用AspectJAutoProxyBeanDefinitionParser类来解析了。其实这两个的解析最终都是向DefaultListableBeanFactory中注册class为AspectJAwareAdvisorAutoProxyCreator的BeanDefinition。而AspectJAwareAdvisorAutoProxyCreator是有实现BeanPostProcessor、BeanFactoryAware接口的。而实例化一个bean的时候会经过这些BeanPostProcessor的处理。也就是这些BeanPostProcessor最终实现了把目标对象代理掉,而用代理前后spring就会调用到配置的这些Advisor来处理一些业务逻辑了。其中的BeanFactoryAware接口是把BeanFactory注入到AspectJAwareAdvisorAutoProxyCreator这个类中,而最终执行方法前通过这里注入的BeanFactory得到这些Advisor类并调用。
这里讲使用java动态代理的实现。在JdkDynamicAopProxy类中。使用到了责任链的模式,会先得到一个Advisor的list,然后在list中用链的方式执行下去。如果chain不是空的则会到ReflectiveMethodInvocation类中执行processed方法。
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { MethodInvocation invocation; Object oldProxy = null; boolean setProxyContext = false; TargetSource targetSource = this.advised.targetSource; Class targetClass = null; Object target = null; try { if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { // The target does not implement the equals(Object) method itself. return equals(args[0]); } if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { // The target does not implement the hashCode() method itself. return hashCode(); } if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) { // Service invocations on ProxyConfig with the proxy config... return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); } Object retVal; if (this.advised.exposeProxy) { // Make invocation available if necessary. oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } // May be null. Get as late as possible to minimize the time we "own" the target, // in case it comes from a pool. target = targetSource.getTarget(); if (target != null) { targetClass = target.getClass(); } // Get the interception chain for this method. List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); // Check whether we have any advice. If we don't, we can fallback on direct // reflective invocation of the target, and avoid creating a MethodInvocation. if (chain.isEmpty()) { // We can skip creating a MethodInvocation: just invoke the target directly // Note that the final invoker must be an InvokerInterceptor so we know it does // nothing but a reflective operation on the target, and no hot swapping or fancy proxying. retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args); } else { // We need to create a method invocation... invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); // Proceed to the joinpoint through the interceptor chain. retVal = invocation.proceed(); } // Massage return value if necessary. if (retVal != null && retVal == target && method.getReturnType().isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { // Special case: it returned "this" and the return type of the method // is type-compatible. Note that we can't help if the target sets // a reference to itself in another returned object. retVal = proxy; } return retVal; } finally { if (target != null && !targetSource.isStatic()) { // Must have come from TargetSource. targetSource.releaseTarget(target); } if (setProxyContext) { // Restore old proxy. AopContext.setCurrentProxy(oldProxy); } } }
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); } }
这里的interceptorOrInterceptionAdvice都是MethodInterceptor类型。因为解析xml的时候,会把<aop:advisor>最终生成class为DefaultBeanFactoryPointcutAdvisor类的BeanDefinition类,而<aop:aspect>会生成class为AspectJPointcutAdvisor的BeanDefinition。又通过DefaultAdvisorAdapterRegistry类把Advisor转换为MethodInterceptor类。
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable { ........................... public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException { List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(3); Advice advice = advisor.getAdvice(); if (advice instanceof MethodInterceptor) { interceptors.add((MethodInterceptor) advice); } for (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()]); } public void registerAdvisorAdapter(AdvisorAdapter adapter) { this.adapters.add(adapter); } }
像beforeAdvisor则转换为MethodBeforeAdviceInterceptor这样的拦截器了。在这个拦截器中的invoke方法中会发现会先调用自己advice的before方法,也就是你自己实现的业务类。接着又会调用processed,也就是连接链的方式,一直调用下去,知道chain中所有都执行完成。
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable { private MethodBeforeAdvice advice; /** * Create a new MethodBeforeAdviceInterceptor for the given advice. * @param advice the MethodBeforeAdvice to wrap */ public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) { Assert.notNull(advice, "Advice must not be null"); this.advice = advice; } public Object invoke(MethodInvocation mi) throws Throwable { this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() ); return mi.proceed(); } }
这里的advice
发表评论
-
spring4.0源码分析之━━━DefaultNamespaceHandlerResolver类
2013-08-07 22:25 3090之所以讲解DefaultNamespaceHa ... -
spring4.0源码分析之注解━━━Annotation
2013-08-08 10:42 4934Annotation比 ... -
spring4.0源码分析解析xml补充━━━(PluggableSchemaResolver类)
2013-08-06 08:37 1681上面一篇文件讲了BeanDefinitio ... -
spring4.0源码分析━━━(AbstractBeanDefinition类)
2013-08-05 11:17 2315上一篇有讲解析xml,其中有说道BeanDefinitio ... -
spring4.0源码分析━━━实例化Bean(AbstractAutowireCapableBeanFactory类)
2013-07-31 14:41 5166实例化bean和依赖注入是在A ... -
spring4.0源码分析━━━(AbstractBeanFactory类分析)
2013-07-31 12:07 2642AbstractBeanFacto ... -
spring4.0源码分析━━━(实例化bean)
2013-07-29 09:21 1566前面有一篇说了spring的解析xml ... -
spring4.0源码分析━━━(解析xml)
2013-07-26 16:34 3216最近比较闲 ...
相关推荐
使用spring4.0进行用户日志的记录 这里带junit的测试跟main的测试 参考了 http://blog.csdn.net/oathevil/article/details/7288867 本代码中还包括了一个java自带注解的例子写的都非常易懂对于hellospring中第一位...
AOP流程源码分析-SpringAOP中定义的类图AOP流程源码分析-SpringAOP中定义的类图AOP流程源码分析-SpringAOP中定义的类图AOP流程源码分析-SpringAOP中定义的类图AOP流程源码分析-SpringAOP中定义的类图AOP流程源码分析...
Spring4.0+Hibernate4.0+Struts2.3整合案例:实现增删改查。 ===================== application.xml: xmlns="http://www.springframework.org/schema/beans" xmlns:xsi=...
Spring-Aop源码实现
有关于Spring,我们最常用的两个功能就是IOC和AOP,前几篇文章从源码级别介绍了Spring容器如何为我们生成bean及bean之间的依赖关系... 确实,Spring也就是通过这两种方式来实现AOP相关功能,下面就通过源码来简单求证下
Spring 4.0 AOP 面向切面测试程序,涉及通知类型包括前置通知\后置通知\返回通知\异常通知\环绕通知,项目采用Maven搭建!
spring4.0和hibernate4.0框架的标准整合,此框架实现了hibernate根据实体自动创建表(前提是你要在mysql中创建名为testspring的库),spring的aop拦截功能,帮助了解aop,和spring事物控制,异常回滚以及junit4的测试...
Spring源代码解析(七):Spring AOP中对拦截器调用的实现 Spring源代码解析(八):Spring驱动Hibernate的实现 Spring源代码解析(九):Spring Acegi框架鉴权的实现 Spring源代码解析(十):Spring Acegi框架授权...
spring mvc beans core webmvc aop jdbc 相关jar 下载
基于注解实现SpringAop基于注解实现SpringAop基于注解实现SpringAop
Java流行框架源码分析:Spring源码、SpringBoot源码、SpringAOP源码、SpringSecurity源码、SpringSecurity OAuth2源码、JDK源码、Netty源码
框架: Spring 实现了使用简单的组件配置组合成一个复杂的应用. 在 Spring 中可以使用 XML 和 Java 注解组合这些对象 一站式:在 IOC 和 AOP 的基础上可以整合各种企业应用的开源框架和优秀的第三方类库 (Spring ...
Java spring AOP源码
Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。Spring AOP:通过配置管理特性,Spring AOP 模块直接将面向方面的编程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何对象...
spring aop spring aop spring aop spring aop spring aop spring aop spring aop spring aop spring aop
NULL 博文链接:https://zhang-yingjie-qq-com.iteye.com/blog/319927
1.Spring入门和IOC介绍 2.对象依赖 3.AOP入门 4.JDBCTemplate和Spring事务 5.Spring事务原理 6.Spring事务的一个线程安全问题 7.IOC再回顾和面试题 8.AOP再回顾
spring-aop-1.1.1.jar spring-aop-1.2.6.jar spring-aop-1.2.9.jar spring-aop-2.0.2.jar spring-aop-2.0.6.jar spring-aop-2.0.7.jar spring-aop-2.0.8.jar spring-aop-2.0.jar spring-aop-2.5.1.jar spring-aop-...
使用Spring的注解方式实现AOP的细节
NULL 博文链接:https://ylxy3058.iteye.com/blog/2224244