使用AspectJ LTW(Load Time Weaving)【转载】

来源:互联网 发布:市政工程预算软件 编辑:程序博客网 时间:2024/06/03 08:16

原文地址:http://log-cd.iteye.com/blog/562056

在Java 语言中,从织入切面的方式上来看,存在三种织入方式:编译期织入、类加载期织入和运行期织入。编译期织入是指在Java编译期,采用特殊的编译器,将切面织入到Java类中;而类加载期织入则指通过特殊的类加载器,在类字节码加载到JVM时,织入切面;运行期织入则是采用CGLib工具或JDK动态代理进行切面的织入。
    AspectJ采用编译期织入和类加载期织入的方式织入切面,是语言级的AOP实现,提供了完备的AOP支持。它用AspectJ语言定义切面,在编译期或类加载期将切面织入到Java类中。
    AspectJ提供了两种切面织入方式,第一种通过特殊编译器,在编译期,将AspectJ语言编写的切面类织入到Java类中,可以通过一个Ant或Maven任务来完成这个操作;第二种方式是类加载期织入,也简称为LTW(Load Time Weaving)。
    使用AspectJ LTW有两个主要步骤,第一,通过JVM的-javaagent参数设置LTW的织入器类包,以代理JVM默认的类加载器;第二,LTW织入器需要一个 aop.xml文件,在该文件中指定切面类和需要进行切面织入的目标类。

    设置-javaagent JVM参数的方法:
(1)在Eclipse下的设置:
运行类->右键单击->Run As->Run...,可以在弹出的Run设置窗口设置该类的各项运行属性,切换到Arguments Tab页,在VM arguments中通过-javaagent指定AspectJ 织入器类包。-javaagent:E:\workspace\lib\spring2.5\aspectjweaver.jar
(2)在Tomcat下的设置
打开<Tomcat_Home>\bin\catalina.bat,在该批处理文件头部添加以下的设置:
set JAVA_OPTS=-javaagent:E:\workspace\lib\spring2.5\aspectjweaver.jar

一、配置LTW织入器的aop.xml配置文件
    LTW织入器在工作时,首先会查找类路径下META-INF /aop.xml的配置文件,并根据配置文件的设置进行织入的操作。

Xml代码  收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <aspectj>  
  3.     <aspects>  
  4.         <!-- ①切面类 -->  
  5.         <aspect name="quickstart.aspectj.Monitor" />  
  6.     </aspects>  
  7.     <weaver  
  8.         options="-showWeaveInfo -XmessageHandlerClass:org.springframework.aop.aspectj.AspectJWeaverMessageHandler">  
  9.         <!-- ② 指定需要进行织入操作的目标类范围 -->  
  10.         <include within="quickstart.service..*" />  
  11.     </weaver>  
  12. </aspectj>  

二、切面织入的目标类和切面实例
Java代码  收藏代码
  1. package quickstart.service.impl;  
  2.   
  3. import java.util.List;  
  4.   
  5. import org.springframework.beans.factory.annotation.Autowired;  
  6. import org.springframework.beans.factory.annotation.Qualifier;  
  7. import org.springframework.transaction.annotation.Propagation;  
  8. import org.springframework.transaction.annotation.Transactional;  
  9.   
  10. import quickstart.dao.PersonDao;  
  11. import quickstart.model.Person;  
  12. import quickstart.service.PeopleService;  
  13.   
  14. public class PeopleServiceImpl implements PeopleService{  
  15.       
  16.     //通过类型(byType为默认)的自动连接可能会有多个候选,  
  17.     //通过使用@Qualifier注解,使用名称(byName)来限定  
  18.     @Autowired  
  19.     @Qualifier("personDao")  
  20.     private PersonDao personDao;  
  21.       
  22.     @Transactional(propagation = Propagation.REQUIRED)  
  23.     public void savePerson(Person person) {  
  24.         personDao.save(person);  
  25.     }  
  26.   
  27.     @Transactional(readOnly = true, propagation = Propagation.REQUIRED)  
  28.     public Person findPersonById(Integer id) {  
  29.         return personDao.findById(id);  
  30.     }  
  31.   
  32.     @Transactional(readOnly = true, propagation = Propagation.REQUIRED)  
  33.     public List findPersonByJPQL(String jpql){  
  34.         return personDao.findByJPQL(jpql);  
  35.     }  

Java代码  收藏代码
  1. package quickstart.aspectj;  
  2.   
  3. import org.aspectj.lang.JoinPoint;  
  4. import org.aspectj.lang.annotation.Aspect;  
  5. import org.aspectj.lang.annotation.Before;  
  6. import org.aspectj.lang.annotation.Pointcut;  
  7.   
  8. @Aspect  
  9. public class Monitor {  
  10.   
  11.     @Pointcut("execution(* quickstart.service.impl.*.*(..))")  
  12.     public void anyService(){}  
  13.   
  14.       
  15.     @Before("quickstart.aspectj.Monitor.anyService()")  
  16.     public void log(JoinPoint joinPoint){  
  17.         System.out.println("Service Method " + joinPoint.getSignature().getName() + " Invocation!");  
  18.     }  
  19. }  

三、Spring配置文件applicationContext.xml
Xml代码  收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.     xmlns:aop="http://www.springframework.org/schema/aop"  
  5.     xmlns:tx="http://www.springframework.org/schema/tx"  
  6.     xsi:schemaLocation="  
  7.     http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd  
  8.     http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd  
  9.     http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">  
  10.   
  11.     <!-- 需要指定factory-method="aspectOf"属性,以便确保Spring从AspectJ获取切面实例,而非自己创建该实例。 -->  
  12.     <bean id="momitor" class="quickstart.aspectj.Monitor"  factory-method="aspectOf"/>  
  13.       
  14.     <!-- 自动装配注解Bean后置处理器 -->  
  15.     <bean   
  16.         class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>  
  17.       
  18.     <!-- JPA注解Bean后置处理器 -->  
  19.     <bean  
  20.         class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />  
  21.   
  22.     <!-- 利用Spring的实体管理器工厂来创建JPA实体管理器 -->  
  23.     <bean id="entityManagerFactory"  
  24.         class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">  
  25.         <property name="dataSource" ref="dataSource" />  
  26.         <property name="jpaVendorAdapter">  
  27.             <bean  
  28.                 class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">  
  29.                 <property name="database" value="MYSQL" />  
  30.                 <property name="showSql" value="true" />  
  31.                 <!-- <property name="generateDdl" value="true" /> -->  
  32.             </bean>  
  33.         </property>  
  34.     </bean>  
  35.   
  36.     <bean id="dataSource"  
  37.         class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
  38.         <property name="driverClassName" value="com.mysql.jdbc.Driver" />  
  39.         <property name="url" value="jdbc:mysql://localhost/test?useUnicode=true&amp;characterEncoding=UTF-8" />  
  40.         <property name="username" value="root" />  
  41.         <property name="password" value="root" />  
  42.     </bean>  
  43.       
  44.     <!-- 声明一个Spring提供的JPA事务管理器,传入的参数是Spring中的实体管理器工厂 -->   
  45.     <bean id="transactionManager"  
  46.         class="org.springframework.orm.jpa.JpaTransactionManager">  
  47.         <property name="entityManagerFactory" ref="entityManagerFactory" />  
  48.     </bean>  
  49.   
  50.     <!-- 开启Spring提供的基于注解的声明式事务管理 -->  
  51.     <tx:annotation-driven transaction-manager="transactionManager" />  
  52.       
  53.     <!-- 直接使用Spring的 JpaTemplate -->  
  54.     <bean id="jpaTemplate" class="org.springframework.orm.jpa.JpaTemplate">  
  55.         <property name="entityManagerFactory" ref="entityManagerFactory" />  
  56.     </bean>  
  57.   
  58.     <bean id="personDao" class="quickstart.dao.impl.PersonDaoImpl" autowire="byName"/>  
  59.       
  60.     <bean id="peopleService" class="quickstart.service.impl.PeopleServiceImpl"/>  
  61. </beans>  

四、测试
Java代码  收藏代码
  1. package logcd.test;  
  2.   
  3. import java.util.List;  
  4.   
  5. import org.junit.BeforeClass;  
  6. import org.junit.Ignore;  
  7. import org.junit.Test;  
  8. import org.springframework.context.ApplicationContext;  
  9. import org.springframework.context.support.ClassPathXmlApplicationContext;  
  10.   
  11. import quickstart.model.Address;  
  12. import quickstart.model.Person;  
  13. import quickstart.service.PeopleService;  
  14.   
  15.   
  16. public class JpaServiceTest {  
  17.   
  18.     private static ApplicationContext appContext;  
  19.     private static PeopleService peopleService;  
  20.       
  21.     @BeforeClass    
  22.     public static void Init(){     
  23.         appContext = new ClassPathXmlApplicationContext("applicationContext.xml");  
  24.         peopleService = (PeopleService)appContext.getBean("peopleService");  
  25.     }   
  26.       
  27.     @Test  
  28.     public void findById(){  
  29.         Person person = peopleService.findPersonById(new Integer(2));  
  30.         System.out.println(person.getFirstName()+person.getLastName());  
  31.         //System.out.println(person.getAddress().getStreetName());  
  32.     }  
  33.       
  34.     @Test  
  35.     public void findByJPQL(){  
  36.         StringBuilder jpql = new StringBuilder();  
  37.         jpql.append(" FROM Person p JOIN FETCH p.address");  
  38.         List list = peopleService.findPersonByJPQL(jpql.toString());  
  39.         for(Object obj : list){  
  40.             Person person = (Person)obj;  
  41.             System.out.println(person.getFirstName() + person.getLastName());  
  42.             System.out.println(person.getAddress().getStreetName());  
  43.         }  
  44.     }  


原创粉丝点击