您的位置:首页 > 编程语言 > Java开发

Spring框架学习笔记2:AOP及其相关概念和使用示例

2012-02-20 10:42 447 查看

1.AOP及其相关概念

1)AOP 面向切面(方面)编程

主要解决共通处理问题.可以将共通处理部分单独用一个组件封装起来,然后利用SpringAOP机制作用到某一批目标对象上面.从而降低共通处理对象和目标对象之间关联.

AOP与OOP关系,OOP面向对象编程,侧重于对象的封装;AOP面向切面编程是以OOP为基础,侧重于对共通处理的操作.改善程序结构,提高灵活性.

2)切面(方面)Aspect
  指的是共通处理部分的代码.也称为关注点的实现.

3)连接点Joinpoint
  指的是作用在目标对象上的位置.例如方法调用,异常发生后等

4)切入点Pointcut
  指的是连接点的集合,对应一个切入点表达式.

5)目标对象Target Object
  指的是使用切面功能的对象.需要在Spring容器中.

6)通知 Advice
  指的是连接点作用的时机.例如方法调用前,方法调用后执行切面功能等.

7)动态代理AutoProxy
  采用AOP之后,Spring会为每一个目标对象创建一个代理对象,该代理对象相当于切面和目标对象功能的结合体.

Spring采用两种方式:
a.JDK Proxy方式
适用于目标对象有接口.
b.CGLIB方式
适用于目标对象没有接口.

2.AOP使用示例

UserDAO.java:

12
3
4
5
6
7
package com.weishuzhai.target;
 
public interface UserDAO {
public void save();
 
public void findByEmail(String email);
}

实现类UserDAOImpl.java:

12
3
4
5
6
78
9
10
1112
13
14
package com.weishuzhai.target;
 
public class JDBCUserDAOImpl implements UserDAO {
 
public void findByEmail(String email) {
System.out.println("采用JDBC技术保存用户信息");
 
}
 
public void save() {
System.out.println("采用JDBC技术查询用户信息");
 
}
}

UserService.java:

12
3
4
5
6
78
9
10
1112
13
14
15
16
17
18
19
20
2122
23
24
25
26
27
28
29
30
3132
package com.weishuzhai.user;
 
import org.junit.Test;
 
import com.weishuzhai.target.UserDAO;
 
public class UserService {
public UserDAO userDao;
 
public void setUserDao(UserDAO userDao) {
this.userDao = userDao;
}
 
/**
* 注册业务方法
*
*/
public void regist() {
// System.out.println("-- 欢迎使用该功能 --");
System.out.println("数据保存成功!谢谢使用!");
userDao.save();
}
 
/**
* 登录业务方法
*
*/
public void login() {
System.out.println("登录成功,谢谢使用!");
userDao.findByEmail("Tom");
}
}

1)示例步骤

a.引入jar包
aspectjweaver.jar
aspectjrt.jar
cglib-nodep-2.1_3.jar
commons-logging.jar
spring.jar
b.寻找关注点,采用切面组件封装.
切面组件MyAspect.java:

12
3
4
5
6
78
9
10
11
package com.weishuzhai.aspect;
 
public class MyAspect {
public void myAspectBefore() {
System.out.println("-- 欢迎使用该功能 --");
}
 
public void myAspectAfter() {
System.out.println("-- 功能使用结束!谢谢使用 --");
}
}

c.在spring配置中添加AOP配置
添加aop命名空间
指定切面

1
<aop:aspect />

定义切入点

1
<aop:pointcut />

指定切入点采用哪种类型的通知

1
<aop:before />

spring配置文件applicationContext.xml:

12
3
4
5
6
78
9
10
1112
13
14
15
16
17
18
19
20
2122
23
24
25
< ?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"
default-lazy-init="true">
<bean id="userDAO" class="com.weishuzhai.target.JDBCUserDAOImpl"/>
<bean id="userService" class="com.weishuzhai.user.UserService">
<property name="userDao" ref="userDAO"></property>
</bean>
<!-- AOP配置 -->
<bean id="myAspect" class="com.weishuzhai.aspect.MyAspect"/>
<aop:config>
<!-- 将myAspect Bean组件指定为切面组件 -->
<aop:aspect id="aspectEx" ref="myAspect">
<!-- 切入点,匹配UserService类中的所有方法 -->
<aop:pointcut id="servicePointcut" expression="execution(* com.weishuzhai.user.UserService.*(..))"></aop:pointcut>
<!-- 定义前置通知.指定切面组件中的myAspectbefore方法,在切入点之前调用 -->
<aop:before pointcut-ref="servicePointcut" method="myAspectBefore"></aop:before>
<!-- 定义最终通知,指定切面组件中的myAspectAfter方法,在切入点之后调用 -->
<aop:after pointcut-ref="servicePointcut" method="myAspectAfter"></aop:after>
</aop:aspect>
</aop:config>
</beans>

d.测试执行TestUserService.java:

12
3
4
5
6
78
9
10
1112
13
14
15
16
17
18
package com.weishuzhai.test;
 
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
import com.weishuzhai.user.UserService;
 
public class TestUserService {
@Test
public void test() {
ApplicationContext ac = new ClassPathXmlApplicationContext(
"applicationContext.xml");
UserService service = (UserService) ac.getBean("userService");
service.regist();
service.login();
}
}

运行结果:

3.通知类型
1)前置通知

1
<aop:before />

目标对象方法调用前执行.
2)后置通知

1
<aop:after -returning/>

目标对象方法成功调用之后执行.
3)最终通知

1
<aop:after />

目标对象方法调用之后执行,不论是成功还是失败.
4)环绕通知

1
<aop:around />

目标对象方法调用之前和之后执行.
5)异常通知

1
<aop:after -throwing/>

目标对象方法调用出现异常后执行.
try{
         前置通知
         环绕通知1
         目标对象方法
         环绕通知1
         后置通知
}catch(){
         异常通知
}finally{
         最终通知
}
4.切入点表达式

*1)方法限定execution

示例1:任意公共方法的执行
execution (public * *(..))
示例2:任何一个名字以“set”开始的方法的执行
execution (* set*(..))
示例3:AccountService中定义的任意方法的执行
execution (* service.AccountService.*(..))
示例4:在service包中定义的任意方法的执行
execution (* service.*.*(..))
示例5:在service包或其子包中定义的任意方法的执行
execution (* service..*.*(..))

*2)类型限定within

示例1:AccountService中定义的任意方法的执行
within (service.AccountService)
示例2:在service包中定义的任意类型的任意方法
within (service.*)
示例3:在service包或其子包中定义的任意类型的任意方法
within (service..*)

*3)Bean对象名限定bean

示例:匹配所有的id或name名字以Service结束的组件
bean(*Service)

4)特定类型限定this或target

this指的是限定特定的代理类型
target指的是限定特定的目标对象类型
示例1:实现了AccountService的代理对象
this (service.AccountService)
示例2:实现了AccountService的目标对象
target (service.AccountService)

5)方法参数限定args

示例:匹配方法有一个String参数的
args (java.lang.String)

—————————–

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: