Spring源码阅读(十一)—AOP补充
2017-10-08 15:19
459 查看
Spring源码阅读(十一)—AOP补充
AOP面向切面编程是面向对象编程的一种补充,广泛应用于事务,日志等场景;AOP实现的关键在于AOP框架能够为目标类创建AOP代理,AOP代理根据创建的形式分为静态代理和动态代理;
静态代理是指在编译期间生成代理类,也成为编译时增强;动态代理是指运行期间借助JDK动态代理或者CGLIB等在内存中临时生成动态代理类,也称为运行时增强;
Spring AOP是运行时增强,AspectJ是编译时增强;Spring AOP为了简化配置使用了和AspectJ一样的注解,但是Spring AOP在运行是依旧是基于动态代理的运行时增强;
个人主页:tuzhenyu’s page
原文地址:Spring源码阅读(十一)—AOP补充
(1)JDK动态代理或CGLIB实现简单的AOP
JDK动态代理实现简单AOP通过定义被代理目标接口,目标实现类,实现了InvacationHandler接口的AOP逻辑实现类,通过Proxy类的newProxyInstance()方法动态生成代理类;代理目标接口
public interface ForumService { public void addTopic(); public void removeTopic(); }
代理目标实现类
public class ForumServiceImpl implements ForumService { public void addTopic(){ System.out.println("in the addTopic"); } public void removeTopic(){ System.out.println("in the removeTopic"); } }
代理横切织入代码
public class PerformanceHandler implements InvocationHandler{ private Object target; public PerformanceHandler(Object target){ this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{ System.out.println("begin monitor..."); Object obj = method.invoke(target,args); System.out.println("end monitor..."); return obj; } }
代理横测试类
public class Main { public static void main(String[] args) { ForumService target = new ForumServiceImpl(); PerformanceHandler handler = new PerformanceHandler(target); ForumService proxy = (ForumService) Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), handler ); proxy.addTopic(); proxy.removeTopic(); } }
(2)通过ProxyFactory简化AOP的实现
为了简化AOP实现过程,可以使用ProxyFactory类,ProxyFactory类是对JDK动态代理和CGLIB动态代理的一个封装,将定义好的目标被代理类和增强Adviceh注入到ProxyFactory中生成代理类实现AOP功能;定义增强
public class UserBeforeAdvice implements MethodBeforeAdvice{ public void before(Method method, Object[] objects, Object o) throws Throwable { System.out.println("before the method"); } }
在XML配置文件中将增强和目标代理类注入到ProxyFactoryBean中
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <bean id="advice" class="aspectj.UserBeforeAdvice"></bean> <bean id="target" class="aspectj.UserServiceImp"></bean> <bean id="userService" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="proxyInterfaces" value="aspectj.UserService"></property> <property name="InterceptorNames" value="advice"></property> <property name="target" value="target"></property> </bean> </beans>
(3)创建切点切面细化AOP操作
Spring通过切点定位到某些类的特定方法上,切点结合增强封装成切面用来具体实现AOP功能定义切面类,在切面类中通过ClassFilter和MethodMatcher进行切点匹配;切面是对切点和增强的封装;
public class UserAdvisor extends StaticMethodMatcherPointcutAdvisor { public boolean matches(Method method, Class<?> aClass) { return "addUser".equals(method.getName()); } }
在XML配置文件中将增强注入到切面中
<bean id="advice" class="aspectj.UserBeforeAdvice"></bean> <bean id="advisor" class="aspectj.UserAdvisor"> <property name="advice" value="advice"></property> </bean>
在XML配置文件中将切面和目标代理类注入到ProxyFactoryBean中
<bean id="advice" class="aspectj.UserBeforeAdvice"></bean> <bean id="advisor" class="aspectj.UserAdvisor"> <property name="advice" value="advice"></property> </bean>
<bean id="target" class="aspectj.UserService"></bean>
<bean id="userService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="aspectj.Services"></property>
<property name="InterceptorNames" value="advisor"></property>
<property name="target" value="target"></property>
</bean>
(4) 通过自动创建代理简化AOP实现
使用ProxyFactoryBean实现AOP,每个需要被代理的Bean都需要使用一个ProxyFactoryBean进行配置;Spring提供了自动代理机制,底层使用BeanPostProcessor实现,在调动getBean()方法获取bean实例时会自动判断该类是否与切面匹配如果匹配则创建代理实例,否则创建普通实例;Spring的自动创建代理主要通过BeanNameAutoProxyCreator类,DefaultAdvisorAutoProxyCreator类,AnnocationAwareAspectjAutoProxyCreator类实现;BeanNameAutoProxyCreator类:主要是为一组特定beanName的bean自动创建代理类,代理全部的方法;
DefaultAdvisorAutoProxyCreator类:扫描容器中的所有Advisor切面,自动将匹配的切面应用到Bean中;
AnnocationAwareAspectjAutoProxyCreator类:对AspectJ注解进行解析,扫描容器中的所有Advisor切面,自动将匹配的切面应用到Bean中;
定义切面类,在切面类中通过ClassFilter和MethodMatcher进行切点匹配;切面是对切点和增强的封装;
public class UserAdvisor extends StaticMethodMatcherPointcutAdvisor { public boolean matches(Method method, Class<?> aClass) { return "addUser".equals(method.getName()); } }
在XML配置文件中将增强注入到切面中
<bean id="advice" class="aspectj.UserBeforeAdvice"></bean> <bean id="advisor" class="aspectj.UserAdvisor"> <property name="advice" value="advice"></property> </bean>
定义DefaultAdvisorAutoProxyCreator实例,自动扫描容器内的切面,并在调用getBean()是判断是否匹配,如果匹配则创建相应的代理类;
<bean id="advice" class="aspectj.UserBeforeAdvice"></bean> <bean id="advisor" class="aspectj.UserAdvisor"> <property name="advice" value="advice"></property> </bean>
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean>
<bean id="userService" class="aspectj.UserService"></bean>
(5) 通过AspectJ注解进一步简化AOP配置
利用@Aspect定义切面类,将增强和切点结合在切面类中@Aspect @Compent public class UserAdvisor { @Before("execution(* addUser(...))") public void before(){ System.out.println("in the before"); } }
定义AnnocationAwareAspectjAutoProxyCreator实例开启AspectJ注解模式,自动扫描容器内的切面,并在调用getBean()是判断是否匹配,如果匹配则创建相应的代理类;
<bean class="org.springframework.aop.framework.autoproxy.AnnocationAwareAspectjAutoProxyCreator"></bean>
如果使用了aop命名空间则使用aop标签定义
<aop:aspectj-autoproxy>
总结
Spring AOP主要是由sping-aop和sping-aspects组成;AOP是一种面向切面编程的思想,是对面向对象的一种补充,在日志以及事务管理等方面有着较多的应用;
AOP实现的关键在于AOP框架能够为目标类创建AOP代理,AOP代理根据创建的形式分为静态代理和动态代理;静态代理是指子啊编译期生成代理类,动态代理是指在运行期间在内存中生成临时代理类;Spring AOP是动态代理,AspectJ是静态代理,虽然Spring引入Aspects包
a6d9
支持AspecJ注解等,但是底层代理实现仍然是通过动态代理;
Spring AOP实现
可以通过JDK动态代理或者CGLIB动态代理直接实现,以JDK动态代理为例,定义目标接口,被代理目标类和实现了AOP逻辑的实现了InnovocationHandler的处理类,调用Proxy类的newProxyInstance()方法生成代理类;
为了简化配置可以使用ProxyFactoryBean,将切点或切面,被代理目标类注入ProxyFactoryBean中生成代理类;
为了进一步简化配置,可以定义自动创建类autoProxyCreator,会在bean实例创建时,搜索容器内的切面,如果匹配则生成代理类实例,如果不匹配则生成普通实例;
为了进一步简化配置,使用AspectJ注解,在切面类上使用@Aspect注解,在容器初始化时会将该切面类加载到容器中,在bean实例创建时,搜索容器内的切面,如果匹配则生成代理类实例,如果不匹配则生成普通实例
相关文章推荐
- Spring源码阅读(六)—AOP获取增强
- Spring源码阅读(五)—AOP基础
- Spring源码阅读-使用ProxyFactoryBean实现AOP
- Spring源码阅读4.1-Aspecjt AOP之获取Adivsor
- Tiny-Spring源码阅读(二)、AOP部分的理解
- Spring源码阅读笔记(待补充)
- Spring源码阅读-注解实现AOP
- Spring源码阅读-通用配置实现AOP
- Spring源码阅读4.2-Aspecjt AOP之代理对象的创建
- spring源码分析之——spring aop原理
- Java程序员从笨鸟到菜鸟之(八十二)细谈Spring(十一)深入理解spring+struts2整合(附源码)
- Spring源码学习之认识AOP
- spring源码阅读(1)bean解析
- 关于Spring中的AOP和事物的源码剖析
- 【Spring源码】AOP部分源码解读
- spring源码学习之路---深入AOP(终)
- 基于Spring源码分析AOP的实现机制
- spring源码解析-AOP原理
- Spring AOP介绍及源码分析
- Spring-Framework 源码阅读之AnnotationBeanUtils