IOC和DI就是为一些类中作为对象的属性、集合、属性文件以及一般类型的变量赋值,即注入。
再本篇中将为大家说明,Spring的第二个核心AOP(面向切面编程)。
举个简单的例子,对于“雇员”这样一个业务实体进行封装,自然是OOP/OOD的任务,我们可以为其建立一个“Employee”类,并将“雇员”相关的属性和行为封装其中。而用AOP设计思想对“雇员”进行封装将无从谈起。
同样,对于“权限检查”这一动作片断进行划分,则是AOP的目标领域。而通过OOD/OOP对一个动作进行封装,则有点不伦不类。
换而言之,OOD/OOP面向名词领域,AOP面向动词领域。
要想面向切面编程,我们首先得了解一些基本的术语以及几种不同的通知:
2.JoinPoint连接点:可能被拦截的方法(服务层中所有的方法);
4.Advice:通知:它指的就是公共模块的能力;
6.Proxy代理类:由Spring提供的代理类来完成通知和切入点的整合
2.后置通知:afterreturnAdvice
3.环绕通知:around
接下来将从手动模式,AOP全自动模式,AspectJ模式的开发;
1手动模式
开发步骤分为三大步和三小步
1) 开发通知类
创建类实现MethodBeforeAdvice—构建前置的通知类
创建类实现aftertrRturnAdvice—构建后置的通知类
创建类实现MethodInterceptor—构建环绕的通知类
再具体的场景种一般只使用一种通知;
2) 再服务层创建接口及其实现类
我们一般会在服务层做一些逻辑的判断
再此时我们开发的公共能力通知类和目标类之间是独立的,所以我们应该创建代理类来将二者整合。
3)配置代理类
<!-- 创建通知类对象-->
<bean id="wwww" class="通知类的路径"></bean>
<!-- 创建目标类对象-->
<bean id="AdviceService" class="目标类的包名+实现类类名"></bean>
<!-- 配置代理对象-->
<bean id="Proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- ProxyFactoryBean工厂类在此处返回的不是自己的对象,而是通过其内部的getObject方法得到对应的代理类的对像-->
<!-- 整合目标类-->
<!--<propertyname="target" ref="目标类的id wwww"></property>-->
<!-- 整合通知类-->
<property name="interceptorNames">
<!-- interceptorNames的原由就是其内部参数是可变参数,可以整合多个通知-->
<list>
<value>AfterAdvice</value>
</list>
</property>
<!-- 关联接口-->
<property name="proxyInterfaces">
<!-- proxyInterfaces其内部参数是一个数组,这样就可以关联多个接口-->
<array>
<value>com.qf.service.UserService</value>
<value>com.qf.service.AdviceService</value>
</array>
</property>
</bean>
2 AOP全自动模式
此方法和之前的方法三大步相同,只不过不需要三小步了,而是直接开启AOP全自动编程
具体的配置如下:
<!-- 创建通知类对象-->
<bean id="AfterAdvice" class="通知类的路径"></bean>
<!-- 创建目标类对象-->
<bean id="UserService" class="目标类的包名+实现类类名"></bean>
<aop:config>
<!-- 切入点:找到目标类中的方法:切入点表达式 -->
<aop:pointcut id="cut" expression="execution(*com.ww.service.*.*(..))"></aop:pointcut>
<!-- 让通知和切入点关联 -->
<aop:advisor advice-ref="AfterAdvice"pointcut-ref="cut"></aop:advisor>
</aop:config>
二者的不同之处就在于后者再得到对象时直接使用的目标类对象的id而对于第一个来说使用的时代理类的id即之前的 Proxy。
在这里解释一下切入表达式:
语法:execution(权限修饰符 返回值类型 包名.类名.方法名.(参数))
execution(* com.ww.service.*.*(..))此为一般格式,当然也不乏有些公司按照模块来划分,只需要稍稍变得即可。
3 AspectJ模式的开发
AspectJ的通知类型:@before@afterreturning @around
AspectJ编写的特点:
不需要实现接口
方法名称随意
通过参数来引入切入点
1)编写公共功能通知类
一般前置的参数为 (JoinPoint joinpoint)括号内几位参数下面相同;
后置的参数为 (JoinPoint joinpoint,Object res)
后置的返回参数是可以返回的;
也就是说,当调用有返回值的参数的时候,函数的返回时会到res当中,可以随着通知输出;
环绕的参数为 (ProceedingJoinPoint joinpoint)
但是环绕同时需要手动来调用方法
参数.proceeding();
2)服务层接口及其实现类的编写
1) AOP全自动编程
让通知和切入点关联形成切面;
<bean id="MyAdvice" class="通知类所在包"></bean>
<bean id="UserService" class="目标类的包名+实现类类名"></bean>
<aop:config>(AOP特有的节点)
(关联自定义对象)
<aop:aspect ref="MyAdvice">
<aop:pointcut id="mypoint"expression="execution(*com.ww.service.*.*(..))">
</aop:pointcut>
aop:after-returning method="具体通知类种的方法名" pointcut-ref="切入点表达式的id" returning="res">此处返回值应该与之前方法种的返回值名称相同
</aop:after-returning>
</aop:aspect>