day43 spring aop_2

前文了解了代理的概念和spring的cglib代理模式,这里要注意的是JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。 

      对于这些概念,这篇文章中帮助我很多http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html

       了解了代理的概念,那么AOP的学习也就水到渠成了。

        首先搭建环境,引入spring-framework-2.5\lib\aspectj下的两个jar包

一、springAOP的具体加载步骤:

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

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

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

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

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

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

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

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

二、参考例子

    结合hibernate框架,用spring aop 在实现一个事务提交例子,最重要的就是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: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="MyTransaction" class="cn.zjy.SpringAop.MyTransaction"></bean>
	<bean id="PersonDaoImpl" class="cn.zjy.SpringAop.PersonDaoImpl"></bean>
	
	<aop:config>
		<aop:pointcut id="personimppoint"
        expression="execution(* cn.zjy.SpringAop.PersonDaoImpl.*(..))"/>
        
        <aop:aspect id="myAspect" ref="MyTransaction">
        	<aop:before method="beginTransaction" pointcut-ref="personimppoint"/>
        	<aop:after-returning method="commit" pointcut-ref="personimppoint"/>
		</aop:aspect>
     </aop:config>
</beans>
        从配置中我们配置了一个切入点和切面,切入点是目标类的方法,切面中包含了通知


目标类

package cn.zjy.SpringAop;

import java.io.Serializable;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class PersonDaoImpl implements PersonDao{

	

	public void deletePerson(Serializable id) {
		Person person = (Person)SessionFactoryUtils.sessionfactory.getCurrentSession().get(Person.class, 2L);
		SessionFactoryUtils.sessionfactory.getCurrentSession().delete(person);
	}

	public String savePerson(Person person) {
		SessionFactoryUtils.sessionfactory.getCurrentSession().save(person);
		return "success";
	}

	public void updatePerson(Person person) {
		
		SessionFactoryUtils.sessionfactory.getCurrentSession().update(person);
	}

}

切面

package cn.zjy.SpringAop;


import org.aspectj.lang.JoinPoint;
import org.hibernate.Transaction;

public class MyTransaction {
	private Transaction transaction;
	public void beginTransaction(JoinPoint jp){
		System.out.println(jp.getSignature().getName());//选择没有process方法的
		
		this.transaction = SessionFactoryUtils.sessionfactory.getCurrentSession().beginTransaction();
	}
	
	public void commit(){
		this.transaction.commit();
	}
}

此时Spring的AOP已经配置好了 写一个客户端程序实现



package cn.zjy.SpringAop;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;


public class SpringAoptest {
	@Test
	public void test()
	{
		ApplicationContext context = new ClassPathXmlApplicationContext("cn/zjy/SpringAop/applicationContext.xml");
		PersonDao persondao = (PersonDao)context.getBean("PersonDaoImpl");
		Person person = new Person();
		person.setPname("haha");
		person.setPsex("nan");
		persondao.savePerson(person);
	}

}

此处仅附上关键代码,项目配置如下



执行结果


三、声明通知

通知:

   1、前置通知

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

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

   2、后置通知

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

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

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

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

   3、最终通知:

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

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

   4、异常通知

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

      2、步骤

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

           在配置文件中

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

   5、环绕通知

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

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

    通过对通知声明的调用,我们可以实现切面的通知与目标类的方法结合的代理类。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值