http://yes100200.blog.163.com/blog/static/9008734620132281828724/
一、为什么会出现AOP
同学们对OOP已经了解,所以我们来一段业务层处理事务代码:
public class UserBizImpl implements IUserBiz{
public void add(){
//事务声明
//执行添加Dao操作
//事务提交
}
public void delete(){
//事务声明
//执行删除Dao操作
//事务提交
}
}
缺点:
混淆了业务方法本身的职责
维护工作量巨大
解决方案:
采用jdk1.3推出的动态代理可以改善。好处在于将事务代码与业务代码完全分离,实现松散耦合.可是,动态代理是大粒度实现。
比如:事务代码只想在某个方法上运行,其它方法不受影响等。InvocationHandler中需要通过硬编码方式写大量逻辑代码过滤方法执行。
非常不利于维护与扩展。好在有了一种全新的编程思想能细粒度的解决此类问题,它就是"AOP"。
二、AOP概述
Aspect-oriented programming:面向切面编程
AOP特点:针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。
AOP目标:专心做事
AOP原理:将散布在系统中的公共功能集中解决
AOP实现:采用动态代理机制
1. 将复杂的需求分解出不同方面
2. 专心做事
3. 组装起来运行[组合—代理方式]
AOP编程术语组成:
1.AOP代理对象:AOP框架创建的对象,用来实现切面执行。
2.Aspect(切面):指系统的某个公共方面【如日志,权限,事务等】
3.Joinpoint(连接点):在程序执行过程中某个特定点。【方法】
4.Advice (通知):在切面的某个特定的连接点上执行的动作.【after,before,around】
5.Pointcut(切点):匹配连接点的断言表达式
6.Target(目标对象):被一个或多个切面所通知的对象
7.Weave(织入):把切面连接到其它的应用程序类型或对象上,并创建一个被通知对象
8.Advisor (织入者[装配器]):將PointCut與Advice組合在一起
工作原理图:
三、AOP在Sprin中应用
准备类
MembersDaoImpl .java
package com.accp.dao.impl;
import com.accp.dao.IMembersDao;
public class MembersDaoImpl implements IMembersDao {
@Override
public void delete() {
System.out.println("删除持久化操作");
}@Override
public void query() {
System.out.println("查询持久化操作");
}@Override
public void save() {
System.out.println("保存持久化操作");
}@Override
public void update() {
System.out.println("修改持久化操作");
}}
MembersBizImpl.java
package com.accp.biz.impl;
import com.accp.biz.IMembersBiz;
import com.accp.dao.IMembersDao;public class MembersBizImpl implements IMembersBiz {
private IMembersDao membersDao;public IMembersDao getMembersDao() {
return membersDao;
}public void setMembersDao(IMembersDao membersDao) {
this.membersDao = membersDao;
}@Override
public void addMembers() {
System.out.println("注册会员");
membersDao.save();}
@Override
public void getMembersList() {
System.out.println("会员列表");
membersDao.query();}
@Override
public void modMembers() {
System.out.println("会员信息更新");
membersDao.update();}
@Override
public void removeMembers() {
System.out.println("清除会员信息");
membersDao.delete();}
}
1.编写专门处理事务的切面类
TransProxy.java
import java.text.SimpleDateFormat;
import java.util.Date;import org.aspectj.lang.ProceedingJoinPoint;
public class TransProxy{
SimpleDateFormat sdf=new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
//前置
public void begin() {
System.out.println(sdf.format(new Date())+":打开数据库连接,并开启事务管理!");
}//后置
public void end() {
System.out.println(sdf.format(new Date())+":关闭数据库连接,并提交事务处理!");
}//环绕通知必须加入ProceedingJoinPoint参数
public void round(ProceedingJoinPoint pjp) {
System.out.println(sdf.format(new Date())+":打开数据库连接,并开启事务管理!");
try {
pjp.proceed();
} catch (Throwable e) {
e.printStackTrace();
}
System.out.println(sdf.format(new Date())+":关闭数据库连接,并提交事务处理!");}
}
2.编写applicationContext.xml文件
<?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: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.5.xsd">
<bean id="biz" class="com.accp.biz.impl.MembersBizImpl" autowire="byName"></bean>
<bean id="membersDao" class="com.accp.dao.impl.MembersDaoImpl"></bean>
<!-- 声明切面 -->
<bean id="trans" class="com.accp.aspect.TransProxy"></bean>
<aop:config><!-- 配置切面 -->
<aop:aspect ref="trans"><!-- 配置切点 -->
<!--aspectJ表达式语法:
within(com.accp.biz.impl.*) 类型匹配
execution(源注释 访问修饰符 返回类型 包名.类名.方法名(参数列表)throws 异常类) 方法匹配
例如:execution(public * add*(..) )
-->
<aop:pointcut expression="execution(public * com.accp.biz.impl.MembersBizImpl.add*(..)) or execution(public * com.accp.biz.impl.MembersBizImpl.get*(..))" id="cut1"/>
<!-- 配置通知 --><!--前置-->
<aop:before method="begin" pointcut-ref="cut1"/><!--后置-->
<aop:after method="end" pointcut-ref="cut1"/><!--环绕-->
<aop:around method="round" pointcut-ref="cut1"/>
</aop:aspect>
</aop:config>
</beans>
3.编写测试类
Test.java
public class Test {
public static void main(String[] args) {
ApplicationContext ctx=new ClassPathXmlApplicationContext("app*.xml");
IMembersBiz biz=(IMembersBiz)ctx.getBean("biz");
biz.getMembersList();
}}
结果所有业务方法都绑定了事务处理代码。
总结:Spring应用AOP非常简单,而且扩展性非常强。希望这篇文章对初学者有帮助。谢谢!