如何理解AOP编程?
一般程序有如下2个部分组成:
1)实现业务功能的业务逻辑代码
2)实现通用功能的通用服务代码
而在AOP则选择将这两种业务进行分离,以达到方便编写和维护效果。
实现案例:
通过模拟一个婚介平台给所有的相亲者介绍对象的流程。
实现步骤:
1:首先开发业务逻辑接口(动态代理只能通过接口所实现)
public interface IXiangQinInterface {
public void meet();
}
2:开发实现业务逻辑接口的类
public class BoyXiangQin implements IXiangQinInterface {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void meet() {
// TODO Auto-generated method stub
System.out.println("姓名是:"+this.name+"正在相亲");
}
}
3编写切面类(通用服务类):几种增强
//提供通用服务(切面类)
public class HunjieAspect {
/*在业务逻辑使用之前使用的方法
* 一般用在权限检查
*/
public void before(){
System.out.println("婚介所开始相亲会员的审查");
}
/* 在业务逻辑使用之后在调用的方法
* 一般用于资源的释放,如数据库连接对象关闭
*/
public void after(){
System.out.println("这次相亲结束");
}
//异常处理,一旦业务逻辑出现异常,那么就调用该方法
//一般主要用于日志记录异常
public void afterException(Throwable th){
System.out.println("相亲出现了意外");
}
//返回值的增强,一般当执行一个业务逻辑方法的时候,如果有返回值,那么就会植入该方法
//一般用于日志记录
public void afterReturn(Object result){
if (result == null) {
System.out.println("相亲失败");
}else{
System.out.println("相亲成功");
}
}
//环绕增强,就是在业务逻辑方法执行期间所植入的方法,一般用于事务处理
public Object around(ProceedingJoinPoint joinpoint ) throws Throwable{
System.out.println("开始约会了!");
Object result = joinpoint.proceed();
return result;
}
}
这里需要导入aop的相关包,否则ProceedingJoinPoint这个找不到
4在spring的配置文件里,编写切面类和业务逻辑类的bean
<!-- 配置切片类的bean -->
<bean id="myPointCut" class="com.spring.bean.HunjieAspect"></bean>
<!-- 配置业务逻辑层的对象 -->
<bean id="boyXiangQin" p:name="张三" class="com.spring.service.imp.BoyXiangQin"></bean>
5修改配置文件的xml验证,实际就是加入aop的命名空间:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
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-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
" >
6配置切面以及切入点和增强
<aop:config>
<!-- 配置切面 -->
<aop:aspect id="myaspect" ref="myPointCut">
<!-- 配置增强和表达式 -->
<!-- 配置切面表达式:表达式表示的是哪些类或者哪些方法要被执行增强-->
<!-- 表示这个包下面的所有类和方法都进行增强中 -->
<aop:pointcut expression="execution(* com.spring.service.imp.*.*(..))" id="mypointexpress"></aop:pointcut>
<aop:before method="before" pointcut-ref="mypointexpress"></aop:before>
<aop:after method="after" pointcut-ref="mypointexpress"></aop:after>
<aop:around method="around" pointcut-ref="mypointexpress"></aop:around>
<aop:after-returning method="afterReturn" returning="result" pointcut-ref="mypointexpress"></aop:after-returning>
<aop:after-throwing method="afterException" throwing="th" pointcut-ref="mypointexpress"></aop:after-throwing>
</aop:aspect>
</aop:config>
7编写实现:注意动态代理只针对接口的实现,所以获取的业务只针对接口
//动态代理只能用接口实现
IXiangQinInterface boyxiang = (IXiangQinInterface)ac.getBean("boyXiangQin");
boyxiang.meet();
关于java中的动态代理模式:
1spring aop中默认采用的是jdk的动态代理。
特点:只能针对接口的实现,也就是在获取这个动态代理对象之后,那么只能通过接口的方式去调用实现。默认值为false
配置:
<aop:config proxy-target-ckass="false"></aop:config>
调用方式:
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
IXiangQinInterface boyxiang = (IXiangQinInterface)ac.getBean("boyXiangQin");
boyxiang.meet();
2另一种采用的是cglib的动态代理,这种动态代理就可以直接针对普通的类来实现代理,改变aopconfig配置
<aop:config proxy-target-ckass="true"></aop:config>
调用方式:
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
BoyXiangQin boyxiang = (BoyXiangQin)ac.getBean("boyXiangQin");
boyxiang.meet();