spring中的AOP 以及各种通知

理解了前面动态代理对象的原理之后,其实还是有很多不足之处,因为如果在项目中有20多个类,每个类有100多个方法都需要判断是不是要开事务,那么方法调用那里会相当麻烦。

spring中的AOP很好地解决了这个问题,通过 execution表达式 指定哪些包中的那些类 哪些方法 用到事务

execution(public *
*(..))  所有的公共方法

execution(*
set*(..)) 
以set开头的任意方法

execution(*
com.xyz.service.AccountService.*(..))
com.xyz.service.AccountService类中的所有的方法

execution(*
com.xyz.service.*.*(..)) 
com.xyz.service包中的所有的类的所有的方法

execution(*
com.xyz.service..*.*(..))
com.xyz.service包及子包中所有的类的所有的方法

execution(* cn.itcast.spring.sh..*.*(String,?,Integer)) 
cn.itcast.spring.sh包及子包中所有的类的有三个参数

第一个参数为String,第二个参数为任意类型,

第三个参数为Integer类型的方法

springAOP的具体加载步骤:

1、当spring容器启动的时候,加载了spring的配置文件

2、为配置文件中所有的bean创建对象

3、spring容器会解析aop:config的配置

1、解析切入点表达式,用切入点表达式和纳入spring容器中的bean做匹配

如果匹配成功,则会为该bean创建代理对象,代理对象的方法=目标方法+通知

如果匹配不成功,不会创建代理对象

4、在客户端利用context.getBean获取对象时,如果该对象有代理对象则返回代理对象,如果代理对象,则返回目标对象

说明:如果目标类没有实现接口,则spring容器会采用cglib的方式产生代理对象,如果实现了接口,会采用jdk的方式

实例:

引入包

aspectjrt.jar

aspectjweaver.jar

Person.java


 1 package cn.itcast.sh.aop;
2
3
4 import java.io.Serializable;
5
6
7 /**
8 * 对象的序列化的作用:让对象在网络上传输,以二进制的形式传输
9 * @author Think
10 * Serializable标示接口
11 */
12 public class Person implements Serializable{
13 private Long pid;
14 private String pname;
15
16 public Person(){}
17
18 public Person(String pname){
19 this.pname = pname;
20 }
21
22 public Long getPid() {
23 return pid;
24 }
25 public void setPid(Long pid) {
26 this.pid = pid;
27 }
28 public String getPname() {
29 return pname;
30 }
31 public void setPname(String pname) {
32 this.pname = pname;
33 }
34 public String getPsex() {
35 return psex;
36 }
37 public void setPsex(String psex) {
38 this.psex = psex;
39 }
40 private String psex;
41 }

PersonDao.java


1 package cn.itcast.sh.aop;
2
3 public interface PersonDao {
4 public void savePerson(Person person);
5 }

PersonDaoImpl.java


 1 package cn.itcast.sh.aop;
2
3 import org.hibernate.Session;
4
5 import cn.itcast.hibernate.sh.utils.HiberanteUtils;
6
7 public class PersonDaoImpl extends HiberanteUtils implements PersonDao{
8
9 @Override
10 public void savePerson(Person person) {
11 Session session=sessionFactory.getCurrentSession();
12 session.save(person);
13 }
14
15 }

定义切面 MyTransaction.java


 1 package cn.itcast.sh.aop;
2
3 import org.hibernate.Transaction;
4
5 import cn.itcast.hibernate.sh.utils.HiberanteUtils;
6
7 public class MyTransaction extends HiberanteUtils{
8
9 private Transaction tran;
10 public void beginTransaction()
11 {
12 tran=sessionFactory.getCurrentSession().beginTransaction();
13 }
14 public void commit()
15 {
16 tran.commit();
17 }
18 }

hibernate.cfg.xml


 1 <?xml version=‘1.0‘ encoding=‘utf-8‘?>
2 <!DOCTYPE hibernate-configuration PUBLIC
3 "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
4 "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
5 <hibernate-configuration>
6 <!--
7 一个session-factory只能连接一个数据库
8 -->
9 <session-factory>
10 <!--
11 数据库的用户名
12 -->
13 <property name="connection.username">root</property>
14
15 <property name="connection.driver_class">
16 com.mysql.jdbc.Driver
17 </property>
18
19 <!--
20 密码
21 -->
22 <property name="connection.password">friends</property>
23 <!--
24 url
25 -->
26 <property name="connection.url">
27 jdbc:mysql://localhost:3306/hibernate_basic
28 </property>
29 <!--
30 作用:根据持久化类和映射文件生成表
31 validate
32 create-drop
33 create
34 update
35 -->
36 <property name="hbm2ddl.auto">update</property>
37
38 <property name="hibernate.dialect">
39 org.hibernate.dialect.MySQLInnoDBDialect
40 </property>
41 <!-- 用于配置当前线程用的 -->
42 <property name="current_session_context_class">thread</property>
43 <!--
44 显示hibernate内部生成的sql语句
45 -->
46 <property name="show_sql">true</property>
47 <property name="format_sql">true</property>
48 <mapping resource="cn/itcast/sh/aop/Person.hbm.xml" />
49
50 </session-factory>
51 </hibernate-configuration>

重点applicationContext-aop.xml配置spring提供的切面


 1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="http://www.springframework.org/schema/beans"
3 xmlns:aop="http://www.springframework.org/schema/aop"
4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5 xsi:schemaLocation="http://www.springframework.org/schema/beans
6 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
7 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
8 <!--
9 导入目标类,导入切面
10 -->
11 <bean id="personDao" class="cn.itcast.sh.aop.PersonDaoImpl"></bean>
12
13 <bean id="myTransaction" class="cn.itcast.sh.aop.MyTransaction"></bean>
14
15 <!--
16 aop的配置
17 -->
18 <aop:config>
19 <!--
20 切入点表达式
21 -->
22 <aop:pointcut expression="execution(* cn.itcast.sh.aop.PersonDaoImpl.*(..))" id="perform"/>
23 <aop:aspect ref="myTransaction">
24
25 <aop:before method="beginTransaction" pointcut-ref="perform"/>
26 <aop:after-returning method="commit" pointcut-ref="perform"/>
27
28 <!-- <aop:after method="finallyMethod" pointcut-ref="perform"/> -->
29 <!-- <aop:after-throwing method="throwingMethod" pointcut-ref="perform" throwing="ex"/> -->
30 <!-- <aop:around method="aroundMethod" pointcut-ref="perform"/> -->
31 </aop:aspect>
32 </aop:config>
33 </beans>

测试类


 1 package cn.itcast.sh.aop;
2
3 import org.junit.Test;
4 import org.springframework.context.ApplicationContext;
5 import org.springframework.context.support.ClassPathXmlApplicationContext;
6
7 public class test {
8 @Test
9 public void testAop()
10 {
11 Person p=new Person();
12 p.setPname("new comer");
13 p.setPsex("boy");
14
15 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-aop.xml");
16 PersonDao dao=(PersonDao) context.getBean("personDao");
17 dao.savePerson(p);
18 }
19
20 }

示例二: 返回值通过 applicationContext.xml中在通知后面添加参数来配置返回值

例如后置通知中 配置 returinn属性

通知:

1、前置通知

1、在目标方法执行之前执行

2、无论目标方法是否抛出异常,都执行,因为在执行前置通知的时候,目标方法还没有执行,还没有遇到异常

2、后置通知

1、在目标方法执行之后执行

2、当目标方法遇到异常,后置通知将不再执行

3、后置通知可以接受目标方法的返回值,但是必须注意:aop:after-returning标签

后置通知的参数的名称和配置文件中returning="var"的值是一致的

3、最终通知:

1、在目标方法执行之后执行

2、无论目标方法是否抛出异常,都执行,因为相当于finally

4、异常通知

1、接受目标方法抛出的异常信息

2、步骤

在异常通知方法中有一个参数Throwable  ex

在配置文件中

<aop:after-throwing method="throwingMethod" pointcut-ref="perform"
throwing="ex"/>

5、环绕通知      
      用于判断条件是否让目标方法执行

1、如果不在环绕通知中调用ProceedingJoinPoint的proceed,目标方法不会执行

2、环绕通知可以控制目标方法的执行

PersonDaoImpl.java


 1 package cn.itcast.spring.aop.sh;
2
3 import java.lang.reflect.Method;
4
5 import org.junit.Test;
6
7 import cn.itcast.spring.aop.annotation.sh.HibernateUtils;
8 import cn.itcast.spring.aop.annotation.sh.Person;
9
10 public class PersonDaoImpl extends HibernateUtils{
11 public String savePerson(Person person) {
12 // TODO Auto-generated method stub
13 //int a = 1/0;
14 //sessionFactory.getCurrentSession().save(person);
15 System.out.println("aaaa");
16 return "aaaa";
17 }
18 }

用到的类和方法和上面相同,只不过改切面的文件(MyTransaction.java)和 applicationContext-aop.xml文件


 1 package cn.itcast.spring.aop.sh;
2
3 import org.aspectj.lang.JoinPoint;
4 import org.aspectj.lang.ProceedingJoinPoint;
5 import org.hibernate.Transaction;
6
7 import cn.itcast.spring.aop.annotation.sh.HibernateUtils;
8
9 public class MyTransaction extends HibernateUtils{
10 private Transaction transaction;
11 /**
12 * 通过该参数可以获取目标方法的一些信息
13 *在每个通知中都可以加入 JoinPoint joinpoint参数
14 * @param joinpoint
15 */
16 public void beginTransaction(JoinPoint joinpoint){
17 System.out.println("bbb");
18 this.transaction = sessionFactory.getCurrentSession().beginTransaction();
19 }
20                         //var是目标方法的返回值,以上的savePerson函数返回值 aaaa
21 public void commit(Object var){ //保持与 application-aop.xml 中的aop:after-returning元素中 returning中的属性值一致
22 System.out.println(var);
23 this.transaction.commit();
24 }
25
26 public void finallyMethod(){
27 System.out.println("finally method");
28 }
29
30 /**
31 * 异常通知
32 * @param ex
33 */
34 public void throwingMethod(Throwable ex){ //保持与 application-aop.xml 中的aop:after-returning元素中 throwing中的属性值一致
35 System.out.println(ex.getMessage());
36 }
37   //JoinPoint是 ProceedingJoinPoint的父类
38 public void aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable{
39 System.out.println(joinPoint.getSignature().getName());
40 joinPoint.proceed();//调用目标方法
41 System.out.println("aaaasfdasfd");
42 }
43 }

applicationContext-aop.xm


 1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="http://www.springframework.org/schema/beans"
3 xmlns:aop="http://www.springframework.org/schema/aop"
4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5 xsi:schemaLocation="http://www.springframework.org/schema/beans
6 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
7 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
8 <!--
9 导入目标类,导入切面
10 -->
11 <bean id="personDao" class="cn.itcast.spring.aop.sh.PersonDaoImpl"></bean>
12
13 <bean id="myTransaction" class="cn.itcast.spring.aop.sh.MyTransaction"></bean>
14
15 <!--
16 aop的配置
17 -->
18 <aop:config>
19 <!--
20 切入点表达式
21 -->
22 <aop:pointcut expression="execution(* cn.itcast.spring.aop.sh.PersonDaoImpl.*(..))" id="perform"/>
23 <aop:aspect ref="myTransaction">
24 <!--
25 前置通知 <aop:before method="beginTransaction" pointcut-ref="perform"/>
26 后置通知 <aop:after-returning method="commit" pointcut-ref="perform" returning="var"/>
27 --><!--最终通知 异常通知 环绕通知 用于判断是否执行目标对象的-->
28 <aop:after method="finallyMethod" pointcut-ref="perform"/>
29 <aop:after-throwing method="throwingMethod" pointcut-ref="perform" throwing="ex"/>
30 <aop:around method="aroundMethod" pointcut-ref="perform"/>
31 </aop:aspect>
32 </aop:config>
33 </beans>

测试


 1 package cn.itcast.spring.aop.sh;
2
3 import org.junit.Test;
4 import org.springframework.context.ApplicationContext;
5 import org.springframework.context.support.ClassPathXmlApplicationContext;
6
7 import cn.itcast.spring.aop.annotation.sh.Person;
8 import cn.itcast.spring.aop.annotation.sh.PersonDaoImpl;
9
10 public class PersonTest {
11 @Test
12 public void test(){
13 ApplicationContext context = new ClassPathXmlApplicationContext("cn/itcast/spring/aop/sh/applicationContext.xml");
14 PersonDaoImpl personDao = (PersonDaoImpl)context.getBean("personDao");
15 Person person = new Person();
16 person.setPname("aaas");
17 personDao.savePerson(person);
18 }
19 }

spring中的AOP 以及各种通知,布布扣,bubuko.com

时间: 2024-08-07 21:17:56

spring中的AOP 以及各种通知的相关文章

转-Spring Framework中的AOP之around通知

Spring Framework中的AOP之around通知 http://blog.csdn.net/xiaoliang_xie/article/details/7049183 标签: springaop设计模式beanintegerclass 2011-12-07 11:39 6108人阅读 评论(0) 收藏 举报 在第一部分,您看到了如何使用Spring AOP来实现跟踪和记录方面.跟踪和记录都是"消极"方面,因为它们的出现并不会对应用程序的其他行为产生影响.它们都使用了消极的b

spring中的aop注解(整合junit测试)

使用spring中的aop前先来了解一下spring中aop中的一些名词 Joimpoint(连接点):目标对象中,所有可能增强的方法 PointCut(切入点):目标对象,已经增强的方法 Advice(通知/增强):增强的代码 Target(目标对象):被代理对象 Weaving(织入):将通知应用到切入点的过程 Proxy(代理):将通知织入到目标对象之后,形成代理对象 aspect(切面):切入点+通知 一:不使用spring的aop注解 以javaEE中的service层为例 UserS

Spring中的AOP(五)——在Advice方法中获取目标方法的参数

摘要: 本文介绍使用Spring AOP编程中,在增强处理方法中获取目标方法的参数,定义切点表达式时使用args来快速获取目标方法的参数. 获取目标方法的信息 访问目标方法最简单的做法是定义增强处理方法时,将第一个参数定义为JoinPoint类型,当该增强处理方法被调用时,该JoinPoint参数就代表了织入增强处理的连接点.JoinPoint里包含了如下几个常用的方法: Object[] getArgs:返回目标方法的参数 Signature getSignature:返回目标方法的签名 Ob

Java——面向切面编程,Spring中的AOP编程

面向切面编程 AOP思想:将横向重复代码,纵向抽取出来 AOP体现--Filter AOP体现--拦截器 AOP体现--动态代理 Spring中实现AOP思想 原理:Spring可以为容器中管理的对象生成代理对象 代理分为动态代理和cglib代理: 动态代理(优先) 被代理对象必须要实现接口,才能产生代理对象,如果没有接口将不能使用动态代理技术,换句话说,就是代理对象和被代理要实现同一接口 cglib代理 第三方代理技术,cglib代理,可以对任何类生成代理,代理的原理是对目标对象进行继承代理,

2018.12.24 Spring中的aop演示

Aop的最大意义是:在不改变原来代码的前提下,也不对源代码做任何协议接口要求.而实现了类似插件的方式,来修改源代码,给源代码插入新的执行代码. 4.spring中的aop演示 4.1步骤: 1.导包(4+2+2+2+1) 基础包+日志包+aop.aspects+test+weaver+aopalliance 下面两个是spring需要的第三方aop包 com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar com.springsource.or

深入分析JavaWeb Item54 -- Spring中的AOP面向切面编程2

一.在Advice方法中获取目标方法的参数 1.获取目标方法的信息 访问目标方法最简单的做法是定义增强处理方法时,将第一个参数定义为JoinPoint类型,当该增强处理方法被调用时,该JoinPoint参数就代表了织入增强处理的连接点.JoinPoint里包含了如下几个常用的方法: Object[] getArgs:返回目标方法的参数 Signature getSignature:返回目标方法的签名 Object getTarget:返回被织入增强处理的目标对象 Object getThis:返

Spring中的AOP

在上一篇博客中,我们讲了Spring的IOC,以下,我们继续解说Spring的还有一个核心AOP AOP: 在软件业,AOP为Aspect Oriented Programming的缩写.意为:面向切面编程,通过预编译方式和执行期动态代理实现程序功能的统一维护的一种技术. AOP也是Action Oriented Programming 的缩写,意为:面向切面编程,是函数式编程的一种衍生范型.AOP在其它领域也有其它含义. AOP的具体解释: 还是老规矩,站在巨人的肩膀上,看看其它人对AOP的理

Spring中的AOP注解方式和配置方式

今天学习了下spring中的切面编程:结合之前看过的视频.整合一下思路: 基本类: 接口: public interface ArithmeticCalculator { int add(int i, int j); int sub(int i, int j); int mul(int i, int j); int div(int i, int j); } 接口的实现: import org.springframework.stereotype.Component; @Component("ar

Spring(二) Spring中的AOP和属性注入

一.AOP(Aspect Oriented Programing)面向切面编程 AOP的终极目标:让我们可以专心做事 下面通过一个例子来介绍AOP的具体使用 案例的要求:使用AOP实现日志记录系统 ,  核心模块  和    增强  单独  开发  ,运行时再组装 首先定义接口和方法 接口和实现类中的代码,我放在一起了,应该比较简单 package demo04.dao; /** * Created by mycom on 2018/3/5. */ public interface IHello