springAOP的入门例子

来源:互联网 发布:见什么知什么 编辑:程序博客网 时间:2024/06/05 14:36

我们通过操作hibernate保存一个数据来体验一下springAOP功能


需求:利用springAOP把一个person对象存放到数据库中.
需求分析:我们要定义一个接口来实现保存person的方法,然后让目标类来操作数据库保存,同时使用切面的通知来开启/提交事务
构建开发环境:
这里写图片描述
除了这些spring和hibernate的包之外,由于这里需要用到AOP,所以还要导入spring/lib/aspect/下的两个jar包
这里写图片描述


为了方便,在这里我们把全部类放到同一个包中。

步骤:
*首先创建Person类,代码如下:

public class Person implements Serializable{    private long pid;    private String pname;    private String pdescription;    //省略getter/setter}

接下来是该类的映射文件:

<?xml version="1.0" encoding="utf-8"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping>    <!--         把相应的核心类导入     -->    <class name="cn.ansel.aopExample.Person">        <!--             给其中的属性赋值         -->        <id name="pid" length="11">            <generator class="increment"></generator>               </id>        <property name="pname" length="11"></property>        <property name="pdescription" length="111"></property>    </class></hibernate-mapping>

然后是hibernate的配置文件(记得使用图形化界面把Person.hbm.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.password">root</property>    <!--         url        这里的URL指的是数据库的地址,        hibernate是不会帮我们创建数据库的,数据库要我们自己创建!    -->    <property name="connection.url">        jdbc:mysql://localhost:3306/hibernate1    </property>    <!--         作用:根据持久化类和映射文件生成表        validate:只验证        create-drop:在开启hibernate的时候创建表,在关闭hibernate的时候删除表        create:每次打开hibernate的时候都创建表        update:每次打开hibernate的时候先validate如果有修改就update,若没有,就create        有了这个属性hbm2ddl.auto,可以让类生成表    -->    <property name="hbm2ddl.auto">update</property>    <property name="show_sql">true</property>    <!--         如果要使用session.getCurrentSession这个方法的话,就要使用        current_session_context_class属性,并且设置值为thread表示当前的session存放在        当前线程中     -->    <property name="current_session_context_class">thread</property>    <!--         表示domian的映射     -->    <mapping resource="cn/ansel/aopExample/Person.hbm.xml" /></session-factory></hibernate-configuration>

首先我们要创建一个工具类来加载hibernate的配置文件。

public class hibernateUtil {    static SessionFactory sessionFactory;    static{        Configuration configuration=new Configuration();        //加载制定位置及名字的配置文件        configuration.configure("cn/ansel/aopExample/hibernate.cfg.xml");        sessionFactory=configuration.buildSessionFactory();    }}

接下来的就是personDao:把person保存到数据库中

public interface PersonDao {    //为了方便,这里只定义了保存方法    public void savePerson(Person person);}

dao的实现:

/** * 这里除了实现personDao接口,还要继承hibernate的工具类。 * 因为这里的语句是操作数据库的,并且这里使用的时hibernate框架来保存数据, */public class PersonDaoImpl extends hibernateUtil implements PersonDao {    @Override    public void savePerson(Person person) {        //让hibernate发出sql语句        sessionFactory.getCurrentSession().save(person);    }}

接下来是切面的编写:

//事务public class MyTransaction extends hibernateUtil{    private Transaction transaction;    public void beginTransaction(){        //调用当前session来开启事务        transaction=sessionFactory.getCurrentSession().beginTransaction();    }    public void commit(){        transaction.commit();    }}

接下来就是spring配置文件,把切面及目标类放到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">    <!--        细心的人可以发现,这里的scheme约束又多了几行信息      -->         <!--         把目标类和切面配置到配置文件中     -->     <bean id="personDaoImpl" class="cn.ansel.aopExample.PersonDaoImpl"></bean>     <bean id="myTransaction" class="cn.ansel.aopExample.MyTransaction"></bean>     <!--         aop配置      -->      <aop:config>        <!--             aop:pointcut 指的是切入点判断,我们昨天使用的是在拦截器中使用if方法,具体内容可以看上一篇帖子                         但是考虑到如果有很多个dao,那么就要判断很多次,效率会降低            expression   指的是切入点的表达式,该表达式的作用就是调用哪些方法,                         一般都使用简写形式,即只需标明 (* *(..)),                         第一个*是指返回值类型,第二个是指方法全名                         括号中的.. 类似于可变参数的作用,                          在这里我们执行的是目标类PersonDaoImpl 的某个方法            id          是指对这个切入点的唯一标识符         -->        <aop:pointcut expression="execution(* cn.ansel.aopExample.PersonDaoImpl.*(..))" id="perform"/>        <!--             aop:aspect  定义切面,因为要把相应的类定义到配置文件中才算是切面            id          该切面的唯一标识符               ref         该切面的引用对象         -->        <aop:aspect id="mytransaction" ref="myTransaction">            <!--                 aop:before 指的是在执行目标方法之前执行的方法                 pointcut-ref 指的是引用的切入点                method          要引用切入点里面的方法名             -->            <aop:before method="beginTransaction" pointcut-ref="perform"/>            <!--                 aop:after-returning 在目标方法执行完之后,调用的方法                method、pointcut-ref与上意义一样             -->            <aop:after-returning method="commit" pointcut-ref="perform"/>        </aop:aspect>      </aop:config></beans>

配置好之后,接下来的就是测试类:

public class testAOP {    @Test    public void test(){        //加载spring配置文件        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("cn/ansel/aopExample/applicationContext.xml");        //得到目标类        PersonDao dao=(PersonDao) applicationContext.getBean("personDaoImpl");        //存入数据        Person person=new Person();        person.setPname("ansel");        person.setPdescription("fine");        dao.savePerson(person);    }}

运行结果:
这里写图片描述

数据库:
这里写图片描述

注意:
在测试类中getBean获取到的目标类,是一个代理对象
这里写图片描述

0 0
原创粉丝点击