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
package cn.itcast.sh.aop; import java.io.Serializable; /**
* 对象的序列化的作用:让对象在网络上传输,以二进制的形式传输
* @author Think
* Serializable标示接口
*/
public class Person implements Serializable{
private Long pid;
private String pname; public Person(){} public Person(String pname){
this.pname = pname;
} public Long getPid() {
return pid;
}
public void setPid(Long pid) {
this.pid = pid;
}
public String getPname() {
return pname;
}
public void setPname(String pname) {
this.pname = pname;
}
public String getPsex() {
return psex;
}
public void setPsex(String psex) {
this.psex = psex;
}
private String psex;
}
PersonDao.java
package cn.itcast.sh.aop;
public interface PersonDao {
public void savePerson(Person person);
}
PersonDaoImpl.java
package cn.itcast.sh.aop;
import org.hibernate.Session;
import cn.itcast.hibernate.sh.utils.HiberanteUtils;
public class PersonDaoImpl extends HiberanteUtils implements PersonDao{
@Override
public void savePerson(Person person) {
Session session=sessionFactory.getCurrentSession();
session.save(person);
}
}
定义切面 MyTransaction.java
package cn.itcast.sh.aop;
import org.hibernate.Transaction;
import cn.itcast.hibernate.sh.utils.HiberanteUtils;
public class MyTransaction extends HiberanteUtils{
private Transaction tran;
public void beginTransaction()
{
tran=sessionFactory.getCurrentSession().beginTransaction();
}
public void commit()
{
tran.commit();
}
}
hibernate.cfg.xml
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<!--
一个session-factory只能连接一个数据库
-->
<session-factory>
<!--
数据库的用户名
-->
<property name="connection.username">root</property> <property name="connection.driver_class">
com.mysql.jdbc.Driver
</property> <!--
密码
-->
<property name="connection.password">friends</property>
<!--
url
-->
<property name="connection.url">
jdbc:mysql://localhost:3306/hibernate_basic
</property>
<!--
作用:根据持久化类和映射文件生成表
validate
create-drop
create
update
-->
<property name="hbm2ddl.auto">update</property> <property name="hibernate.dialect">
org.hibernate.dialect.MySQLInnoDBDialect
</property>
<!-- 用于配置当前线程用的 -->
<property name="current_session_context_class">thread</property>
<!--
显示hibernate内部生成的sql语句
-->
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<mapping resource="cn/itcast/sh/aop/Person.hbm.xml" /> </session-factory>
</hibernate-configuration>
重点applicationContext-aop.xml配置spring提供的切面
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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="personDao" class="cn.itcast.sh.aop.PersonDaoImpl"></bean> <bean id="myTransaction" class="cn.itcast.sh.aop.MyTransaction"></bean> <!--
aop的配置
-->
<aop:config>
<!--
切入点表达式
-->
<aop:pointcut expression="execution(* cn.itcast.sh.aop.PersonDaoImpl.*(..))" id="perform"/>
<aop:aspect ref="myTransaction"> <aop:before method="beginTransaction" pointcut-ref="perform"/>
<aop:after-returning method="commit" pointcut-ref="perform"/> <!-- <aop:after method="finallyMethod" pointcut-ref="perform"/> -->
<!-- <aop:after-throwing method="throwingMethod" pointcut-ref="perform" throwing="ex"/> -->
<!-- <aop:around method="aroundMethod" pointcut-ref="perform"/> -->
</aop:aspect>
</aop:config>
</beans>
测试类
package cn.itcast.sh.aop; import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class test {
@Test
public void testAop()
{
Person p=new Person();
p.setPname("new comer");
p.setPsex("boy"); ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-aop.xml");
PersonDao dao=(PersonDao) context.getBean("personDao");
dao.savePerson(p);
} }
示例二: 返回值通过 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
package cn.itcast.spring.aop.sh; import java.lang.reflect.Method; import org.junit.Test; import cn.itcast.spring.aop.annotation.sh.HibernateUtils;
import cn.itcast.spring.aop.annotation.sh.Person; public class PersonDaoImpl extends HibernateUtils{
public String savePerson(Person person) {
// TODO Auto-generated method stub
//int a = 1/0;
//sessionFactory.getCurrentSession().save(person);
System.out.println("aaaa");
return "aaaa";
}
}
用到的类和方法和上面相同,只不过改切面的文件(MyTransaction.java)和 applicationContext-aop.xml文件
package cn.itcast.spring.aop.sh; import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.hibernate.Transaction; import cn.itcast.spring.aop.annotation.sh.HibernateUtils; public class MyTransaction extends HibernateUtils{
private Transaction transaction;
/**
* 通过该参数可以获取目标方法的一些信息
*在每个通知中都可以加入 JoinPoint joinpoint参数
* @param joinpoint
*/
public void beginTransaction(JoinPoint joinpoint){
System.out.println("bbb");
this.transaction = sessionFactory.getCurrentSession().beginTransaction();
}
//var是目标方法的返回值,以上的savePerson函数返回值 aaaa
public void commit(Object var){ //保持与 application-aop.xml 中的aop:after-returning元素中 returning中的属性值一致
System.out.println(var);
this.transaction.commit();
} public void finallyMethod(){
System.out.println("finally method");
} /**
* 异常通知
* @param ex
*/
public void throwingMethod(Throwable ex){ //保持与 application-aop.xml 中的aop:after-returning元素中 throwing中的属性值一致
System.out.println(ex.getMessage());
}
//JoinPoint是 ProceedingJoinPoint的父类
public void aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println(joinPoint.getSignature().getName());
joinPoint.proceed();//调用目标方法
System.out.println("aaaasfdasfd");
}
}
applicationContext-aop.xm
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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="personDao" class="cn.itcast.spring.aop.sh.PersonDaoImpl"></bean> <bean id="myTransaction" class="cn.itcast.spring.aop.sh.MyTransaction"></bean> <!--
aop的配置
-->
<aop:config>
<!--
切入点表达式
-->
<aop:pointcut expression="execution(* cn.itcast.spring.aop.sh.PersonDaoImpl.*(..))" id="perform"/>
<aop:aspect ref="myTransaction">
<!--
前置通知 <aop:before method="beginTransaction" pointcut-ref="perform"/>
后置通知 <aop:after-returning method="commit" pointcut-ref="perform" returning="var"/>
--><!--最终通知 异常通知 环绕通知 用于判断是否执行目标对象的-->
<aop:after method="finallyMethod" pointcut-ref="perform"/>
<aop:after-throwing method="throwingMethod" pointcut-ref="perform" throwing="ex"/>
<aop:around method="aroundMethod" pointcut-ref="perform"/>
</aop:aspect>
</aop:config>
</beans>
测试
package cn.itcast.spring.aop.sh; import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import cn.itcast.spring.aop.annotation.sh.Person;
import cn.itcast.spring.aop.annotation.sh.PersonDaoImpl; public class PersonTest {
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("cn/itcast/spring/aop/sh/applicationContext.xml");
PersonDaoImpl personDao = (PersonDaoImpl)context.getBean("personDao");
Person person = new Person();
person.setPname("aaas");
personDao.savePerson(person);
}
}
spring中的AOP 以及各种通知 配置的更多相关文章
- 转-Spring Framework中的AOP之around通知
Spring Framework中的AOP之around通知 http://blog.csdn.net/xiaoliang_xie/article/details/7049183 标签: spring ...
- Spring中的AOP 专题
Caused by: java.lang.IllegalArgumentException: ProceedingJoinPoint is only supported for around advi ...
- Spring学习笔记(四)—— Spring中的AOP
一.AOP概述 AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善.O ...
- 2018.12.24 Spring中的aop演示(也就是运用aop技术实现代理模式)
Aop的最大意义是:在不改变原来代码的前提下,也不对源代码做任何协议接口要求.而实现了类似插件的方式,来修改源代码,给源代码插入新的执行代码. 1.spring中的aop演示 aop:面向方面编程.不 ...
- JavaWeb_(Spring框架)认识Spring中的aop
1.aop思想介绍(面向切面编程):将纵向重复代码,横向抽取解决,简称:横切 2.Spring中的aop:无需我们自己写动态代理的代码,spring可以将容器中管理对象生成动态代理对象,前提是我们对他 ...
- (五)Spring 中的 aop
目录 文章目录 AOP概念 AOP原理 AOP术语 **`Spring`** 中的 **`aop`** 的操作 使用 `AspectJ` 实现 `aop` 的两种方式 AOP概念 浅理解 aop :面 ...
- Spring中的AOP
什么是AOP? (以下内容来自百度百科) 面向切面编程(也叫面向方面编程):Aspect Oriented Programming(AOP),通过预编译方式和运行期动态代理实现程序功能的统一维护的一种 ...
- Spring中关于AOP的实践之概念
一.什么是AOP AOP:也称作面向切面编程 在分享几个概念执行我想先举个栗子(可能例子举得并不是特别恰当): 1.假如路人A走在大街上,被一群坏人绑架了: 2.警察叔叔接到报警迅速展开行动:收集情报 ...
- Spring 中基于 AOP 的 @AspectJ
Spring 中基于 AOP 的 @AspectJ @AspectJ 作为通过 Java 5 注释注释的普通的 Java 类,它指的是声明 aspects 的一种风格. 通过在你的基于架构的 XML ...
随机推荐
- [BZOJ4004][JLOI2015]装备购买(贪心+线性基)
求最小权极大线性无关组. 先将所有向量按权值排序,从小到大依次判断,若能被前面已选向量线性表出则不选,这样一定最优. 据说是用拟阵来证明,但感性理解一下感觉比较显然,首先这样个数一定是最多的,其次对于 ...
- JZYZOJ1383 [usaco2003feb]impster 位运算 最短路
http://172.20.6.3/Problem_Show.asp?id=1383 找能到达某个状态的最小操作数,然后把所有状态扫一遍即可,要额外判定一下起始就有的状态(如果起始里没有0那么这些状 ...
- 2017 icpc 南宁网络赛
2000年台湾大专题...英语阅读输入输出专场..我只能说很强势.. M. Frequent Subsets Problem The frequent subset problem is define ...
- 【动态规划】【线段树】 Codeforces Round #426 (Div. 1) B. The Bakery
给你一个序列,让你划分成K段,每段的价值是其内部权值的种类数,让你最大化所有段的价值之和. 裸dp f(i,j)=max{f(k,j-1)+w(k+1,i)}(0<=k<i) 先枚举j,然 ...
- 【混合背包】CDOJ1606 难喝的饮料
#include<cstdio> #include<algorithm> using namespace std; int n,V,op[20010],c[20010],w[2 ...
- 【优先队列+贪心】POJ2431-Expedition
解题方法详见<挑战程序设计竞赛(第二版)>P74-75.注意首先要对加油站以位置为关键字快排,不要遗忘把终点视作一个加油量为0的加油站,否则最终只能到达终点前的加油站. /*优先队列*/ ...
- 【动态规划】POJ3280- Cheapest Palindrome
[题目大意] 给出一个字符串,可以删除或添加一些字符,它们各自会消耗价值.问最少消耗多少价值,可以使得字符串变成回文的. [思路] 事实上删除或添加字符的价值只需要保持较小的那一个.假设当前要将(j, ...
- ob_flush()和flush()和ob_implicit_flush(true)
http://www.jb51.net/article/16215.htm 第一: “ob_flush()和flush()的区别.前者是把数据从PHP的缓冲中释放出来,后者是把不在缓冲中的或者说是被释 ...
- [典型漏洞分享]从一个手动分析的反射型XSS漏洞看待一个安全设计原则【中危】
这是在测试YS“本地相册”功能时发现的一个反射型XSS,自己在安全测试过程中也发现过不少XSS漏洞,唯独这个的发现过程有点区别. 在此之前,我在测试另外一个模块的功能接口的时候发现了一个反射型XSS, ...
- Jquery 一次处理多个ajax请求的代码
Jquery 一次处理多个ajax请求的代码,需要的朋友可以参考下. 复制代码代码如下: $(document).ready(function () { $('#getsetgo').click( ...