AOP(AspectOriented Programming,面向切面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善,是软件开发中的一个热点,也是Spring框架中的一个重要内容。AOP能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任,例如事务处理、日志管理、权限控制等,封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。
1、Aspect:对横切关注点模块化;
2、Advice:对横切性关注点的具体实现,包括调用目标之前执行(Before Advice)、调用目标之后执行(After Advice)、抛出异常(Throw Advice);
3、Pointcut:横切性关注点的应用范围,它定义了Advice应用到哪些JoinPoint上;应用范围,第一个* 表示所有的有无返回值,第二个*表示有无参数,代表匹配所有情况;
4、JoinPoint:连接点,调用目标方法的地方。在AOP中表示“在哪里做”;
5、Weave:织入,将Advice应用到TargetObject上的过程;
6、Introduction:引入,可以动态地为类添加方法,对类的增强叫做引入(Introduction),对方法的增强叫做织入(Weaving)。
本Demo实现了在调用方法之前检查安全性。
不变的代码:
<span style="font-family:KaiTi_GB2312;font-size:18px;">package com.jmj.spring; /** * ClassName: UserManager * @Description: 接口 * @author meng * @date 2016-5-6 上午10:51:44 */ public interface UserManager { public void addUser(String username, String password); public void delUser(int userId); } </span>
<span style="font-family:KaiTi_GB2312;font-size:18px;">package com.jmj.spring; /** * ClassName: UserManagerImpl * @Description: 具体实现类 * @author meng * @date 2016-5-6 上午10:51:24 */ public class UserManagerImpl implements UserManager { public void addUser(String username, String password) { //checkSecurity(); System.out.println("---------UserManagerImpl.add()--------"); } public void delUser(int userId) { //checkSecurity(); System.out.println("---------UserManagerImpl.delUser()--------"); } } </span>
<span style="font-family:KaiTi_GB2312;font-size:18px;">package com.jmj.spring; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * ClassName: Client * @Description: 客户端 * @author meng * @date 2016-5-6 上午10:52:05 */ public class Client { public static void main(String[] args){ //读取配置文件 BeanFactory factory =new ClassPathXmlApplicationContext("applicationContext.xml"); UserManager userManager=(UserManager)factory.getBean("userManager"); userManager.addUser("张三", "123"); } } </span>重要部分:
1、 在横切类中添加注解
<span style="font-family:KaiTi_GB2312;font-size:18px;">package com.jmj.spring; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; //将横切性关注点模块化 //使用注解方式:Annotation @Aspect public class SecurityHandler { //定义检查安全性在调用添加方法之前 /** * 定义Advice,表示Advice应用到那些PointCut订阅的JoinPoint上 */ //对横切性关注点的具体实现 @Before("addAddMethod()") //前置增强 //@After("addAddMethod()") //后置增强 private void checkSecurity() { System.out.println("-------checkSecurity-------"); } /** * 定义PointCut,PointCut的名称为addAddMethod(),此方法没有返回值和参数 * 该方法是一个标识,不进行调用 */ //横切性关注点的应用范围 //应用范围 ,第一个* 表示所有的有无返回值,第二个*表示有无参数,代表匹配所有情况 @Pointcut("execution(* add*(..))") private void addAddMethod(){}; } </span>
2、 在配置文件(applicationContext.xml)中,启用AspectJ对Annotation的支持
<span style="font-family:KaiTi_GB2312;font-size:18px;"><!--启用AspectJ对Annotation的支持 --> <aop:aspectj-autoproxy/> <bean id="userManager" class="com.jmj.spring.UserManagerImpl"/> <bean id="securityHandler" class="com.jmj.spring.SecurityHandler"/></span>
1、横切类
<span style="font-family:KaiTi_GB2312;font-size:18px;">public class SecurityHandler { private void checkSecurity() { System.out.println("-------checkSecurity-------"); } }</span>此类中,只需要切入方法的具体实现,而不需要管如何切入,何时切入?
2、在配置文件(applicationContext.xml)中,管理具体的切入形式
<span style="font-family:KaiTi_GB2312;font-size:18px;"> <bean id="userManager" class="com.jmj.spring.UserManagerImpl"/> <bean id="securityHandler" class="com.jmj.spring.SecurityHandler"/> <aop:config> <!--相当于注解中的aspect ,对横切关注点的模块化 --> <aop:aspect id="securityAspect" ref="securityHandler"> <!--定义了Advice应用到哪些JoinPoint上,对Spring来说是方法调用 --> <!--以add开头的方法 --> <!-- <aop:pointcut id="addAddMethod" expression="execution(* add*(..))"/> --> <!--可以使用引用包,范围是:com.jmj.spring这个包下的所有类的所有方法 --> <!-- <aop:pointcut id="addAddMethod" expression="execution(* com.jmj.spring.*.*(..))"/> --> <!--只对添加和删除起作用,对以add和del开头的方法起作用 --> <aop:pointcut id="addAddMethod" expression="execution(* com.jmj.spring.*.add*(..)) || execution(* com.jmj.spring.*.del*(..))"/> <!--对横切关注点的具体实现 --> <aop:before method="checkSecurity" pointcut-ref="addAddMethod"/> <!-- <aop:after method="checkSecurity" pointcut-ref="addAddMethod"/> --> </aop:aspect> </aop:config></span>
AOP和OOP的关系,如图所示:
AOP的优点:低耦合,高扩展。