在Spring AOP中,通常需要借助AspectJ的切点表达式语言来定义切点。重要的是Spring中仅支持AspectJ切点指示器的一个子集。

Spring支持的AspectJ的切点指示器

AspectJ指示器 描述 args() 限制连接点匹配参数为执行类型的执行方法 @args() 限制连接点匹配参数由执行注解标注的执行方法 execution() 匹配连接点的执行方法 this() 限制连接点匹配AOP代理的Bean引用类型为指定类型的Bean target() 限制连接点匹配目标对象为指定类型的类 @target() 限制连接点匹配目标对象被指定的注解标注的类 within() 限制连接点匹配匹配指定的类型 @within() 限制连接点匹配指定注解标注的类型 @annotation 限制匹配带有指定注解的连接点

Spring AOP中常用的是:

Java代码

execution(modifiers-pattern?ret-type-patterndeclaring-type-pattern?name-pattern(param-pattern)

throws-pattern?)

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)

匹配所有

execution("* *.*(..)")

匹配所有以set开头的方法

execution("* *.set*(..))

匹配指定包下所有的方法

execution("*com.david.biz.service.impl.*(..))

匹配指定包以及其子包下的所有方法

execution("* com.david..*(..)")

匹配指定包以及其子包下参数类型为String的方法

execution("* com.david..*(java.lang.String))

Java代码

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

xmlns:p="http://www.springframework.org/schema/p"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:context="http://www.springframework.org/schema/context"xmlns:tx="http://www.springframework.org/schema/tx"

xmlns:aop="http://www.springframework.org/schema/aop"xmlns:jee="http://www.springframework.org/schema/jee"

xmlns:task="http://www.springframework.org/schema/task"

xsi:schemaLocation="

http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context-3.0.xsd

http://www.springframework.org/schema/aop

http://www.springframework.org/schema/aop/spring-aop-3.0.xsd

http://www.springframework.org/schema/tx

http://www.springframework.org/schema/tx/spring-tx-3.0.xsd

http://www.springframework.org/schema/jee

http://www.springframework.org/schema/jee/spring-jee-3.0.xsd

http://www.springframework.org/schema/task

http://www.springframework.org/schema/task/spring-task-3.1.xsd

">

<context:component-scanbase-package="com.david.*"/>

<aop:aspectj-autoproxy/>

<context:property-placeholderlocation="classpath:META-INF/config.properties"/>

<!--定义数据源-->

<beanid="dataSource"class="com.mchange.v2.c3p0.ComboPooledDataSource"

destroy-method="close">

<propertyname="driverClass"value="${jdbc.ams.driver}"/>

<propertyname="jdbcUrl"value="${jdbc.ams.url}"/>

<propertyname="user"value="${jdbc.ams.username}"/>

<propertyname="password"value="${jdbc.ams.password}"/>

<propertyname="initialPoolSize"value="${initialSize}"/>

<propertyname="minPoolSize"value="${minPoolSize}"/>

<propertyname="maxPoolSize"value="${maxActive}"/>

<propertyname="acquireIncrement"value="${acquireIncrement}"/>

<propertyname="maxIdleTime"value="${maxIdleTime}"/>

</bean>

<!--定义jdbc模板类-->

<beanid="jdbcTemplate"class="org.springframework.jdbc.core.JdbcTemplate">

<propertyname="dataSource"ref="dataSource"/>

</bean>

<beanid="sqlMapClient"class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">

<propertyname="dataSource"ref="dataSource"/>

<propertyname="configLocation"value="classpath:META-INF/sqlmap/sqlmap.xml"/>

</bean>

<tx:adviceid="txAdvice"transaction-manager="transactionManager">

<tx:attributes>

<tx:methodname="addBook"propagation="REQUIRED"/>

<tx:methodname="addUserBook"propagation="MANDATORY"/>

<tx:methodname="deleteBook"propagation="REQUIRES_NEW"/>

<tx:methodname="addNewBook"propagation="NEVER"/>

<tx:methodname="addUser"propagation="NESTED"/>

</tx:attributes>

</tx:advice>

<beanid="transactionManager"

class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

<propertyname="dataSource"ref="dataSource"/>

</bean>

</beans>

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"xmlns:aop="http://www.springframework.org/schema/aop" xmlns:jee="http://www.springframework.org/schema/jee"xmlns:task="http://www.springframework.org/schema/task"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.0.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-3.0.xsdhttp://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsdhttp://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd "><context:component-scan base-package="com.david.*"/><aop:aspectj-autoproxy /><context:property-placeholder location="classpath:META-INF/config.properties" /><!-- 定义数据源 --><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"destroy-method="close"><property name="driverClass" value="${jdbc.ams.driver}" /><property name="jdbcUrl" value="${jdbc.ams.url}" /><property name="user" value="${jdbc.ams.username}" /><property name="password" value="${jdbc.ams.password}" /><property name="initialPoolSize" value="${initialSize}" /><property name="minPoolSize" value="${minPoolSize}" /><property name="maxPoolSize" value="${maxActive}" /><property name="acquireIncrement" value="${acquireIncrement}" /><property name="maxIdleTime" value="${maxIdleTime}" /></bean><!-- 定义jdbc模板类 --><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource" /></bean><bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"><property name="dataSource" ref="dataSource" /><property name="configLocation" value="classpath:META-INF/sqlmap/sqlmap.xml" /></bean><tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><tx:method name="addBook" propagation="REQUIRED" /><tx:method name="addUserBook" propagation="MANDATORY" /><tx:method name="deleteBook" propagation="REQUIRES_NEW" /><tx:method name="addNewBook" propagation="NEVER" /><tx:method name="addUser" propagation="NESTED" /></tx:attributes></tx:advice><bean id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource" /></bean></beans>

Java代码

@Service("bookService")

publicclassBookServiceImplimplementsBookService{

privatestaticfinalLoggerlogger=LogManager.getLogger(BookServiceImpl.class);

publicstaticfinalStringADD_BOOK="insertintot_book(id,name)values(1,'duck-j2ee')";

publicstaticfinalStringDELETE_BOOK="deletefromt_bookwhereid=1";

privateJdbcTemplatejdbcTemplate;

@Autowired

privateBookDaobookDao;

publicvoidaddBook()throwsException{

Bookbook=newBook();

book.setName("ibatis");

book.setPrice(11);

bookDao.insert(book);

thrownewUnRollbackException("受检查异常,不会回滚");

}

publicvoiddeleteBook(intid){

try{

bookDao.deleteById(id);

}catch(SQLExceptione){

logger.error("",e);

}

}

@LoggingRequired

publicvoidaddNewBook(Stringname,intprice){

try{

Bookbook=newBook();

book.setName(name);

book.setPrice(price);

bookDao.insert(book);

List<Book>lists=bookDao.selectAll();

System.out.println(lists);

}catch(SQLExceptione){

logger.error("",e);

}

}

publicvoidaddUserBook(){

jdbcTemplate.execute("insertintot_book(id,name)values(3,'UserBook')");

}

/**

*Settermethodforproperty<tt>jdbcTemplate</tt>.

*

*@paramjdbcTemplatevaluetobeassignedtopropertyjdbcTemplate

*/

publicvoidsetJdbcTemplate(JdbcTemplatejdbcTemplate){

this.jdbcTemplate=jdbcTemplate;

}

/**

*@seecom.david.biz.service.BookService#queryAll()

*/

publicList<Book>queryAll(){

try{

returnbookDao.selectAll();

}catch(SQLExceptione){

logger.error("",e);

}

returnnull;

}

}

@Service("bookService")public class BookServiceImpl implements BookService { private static final Logger logger = LogManager.getLogger(BookServiceImpl.class); public static final String ADD_BOOK = "insert into t_book(id,name) values(1,'duck-j2ee')"; public static final String DELETE_BOOK = "delete from t_book where id=1"; private JdbcTemplate jdbcTemplate; @Autowired private BookDao bookDao; public void addBook() throws Exception { Book book = new Book(); book.setName("ibatis"); book.setPrice(11); bookDao.insert(book); throw new UnRollbackException("受检查异常,不会回滚"); } public void deleteBook(int id) { try { bookDao.deleteById(id); } catch (SQLException e) { logger.error("", e); } } @LoggingRequired public void addNewBook(String name, int price) { try { Book book = new Book(); book.setName(name); book.setPrice(price); bookDao.insert(book); List<Book> lists = bookDao.selectAll(); System.out.println(lists); } catch (SQLException e) { logger.error("", e); } } public void addUserBook() { jdbcTemplate.execute("insert into t_book(id,name) values(3,'UserBook')"); } /** * Setter method for property <tt>jdbcTemplate</tt>. * * @param jdbcTemplate value to be assigned to property jdbcTemplate */ public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } /** * @see com.david.biz.service.BookService#queryAll() */ public List<Book> queryAll() { try { return bookDao.selectAll(); } catch (SQLException e) { logger.error("", e); } return null; }}

Java代码

/**

*execution(modifiers-pattern?ret-type-patterndeclaring-type-pattern?name-pattern(param-pattern)

throws-pattern?)

*arg()限制连接点匹配参数为指定类型的执行方法

*@args()限制连接点匹配参数由执行注解标注的执行

*execution()用于匹配连接点的执行方法

*this()限制连接点匹配AOP代理的Bean引用为执行类型的类

*target()限制连接点匹配目标对象为指定类型的类

*@target()限制连接点匹配特定的执行对象,这些对象应具备指定的注解类型

*@annotation()限制匹配带有指定注解的连接点

*

*

*

*@authorzhangwei_david

*@version$Id:LogAspect.java,v0.12014年11月29日下午1:10:13zhangwei_davidExp$

*/

@Component

@Aspect

publicclassLogAspect{

privatestaticfinalLoggerlogger=LogManager.getLogger(LogAspect.class);

/**

*匹配参数是任何类型,任何数量且在com,david.biz包或子包下的方法

*/

@Pointcut("args(..)&&within(com.david.biz..*)")

publicvoidarg(){

}

@Pointcut("@args(com.david.aop.LoggingRequired)")

publicvoidannotationArgs(){

}

@Pointcut("@annotation(com.david.aop.LoggingRequired)")

publicvoidlogRequiredPointcut(){

}

@Pointcut("args(java.lang.String,*)")

publicvoidargsWithString(){

}

@Pointcut("target(com.david.biz.service.impl.BookServiceImpl)")

publicvoidtargetPointcut(){

}

@Pointcut("@target(org.springframework.stereotype.Service)")

publicvoidtargetAnnotation(){

}

//@Around("execution(*org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(..))")

//publicObjectaa(ProceedingJoinPointpjp)throwsThrowable{

//try{

//ObjectretVal=pjp.proceed();

//System.out.println(retVal);

//returnretVal;

//}catch(Exceptione){

//System.out.println("异常");

//returnnull;

//}

//}

@Before(value="logRequiredPointcut()")

publicvoidbefore(JoinPointjoinPoint){

LogUtils.info(logger,

"连接点表达式@annotation(com.david.aop.LoggingRequired)-method={0}hasbeenvisited",

joinPoint.getSignature().getName());

}

@Before(value="arg()")

publicvoidbeforeArg(JoinPointjoinPoint){

LogUtils.info(logger,

"连接点表达式:args(..)&&within(com.david.biz..*)method={0},args={1},target={2}",

joinPoint.getSignature().getName(),ToStringBuilder.reflectionToString(

joinPoint.getArgs(),ToStringStyle.SHORT_PREFIX_STYLE),joinPoint.getTarget()

.getClass().getName());

}

@Before(value="argsWithString()")

publicvoidbeforeArgWithString(JoinPointjoinPoint){

LogUtils.info(logger,"连接点表达式:args(java.lang.String,*)method={0},args={1},target={2}",

joinPoint.getSignature().getName(),ToStringBuilder.reflectionToString(

joinPoint.getArgs(),ToStringStyle.SHORT_PREFIX_STYLE),joinPoint.getTarget()

.getClass().getName());

}

@Before(value="annotationArgs()")

publicvoidbeforeAnnotationArgs(JoinPointjoinPoint){

LogUtils

.info(

logger,

"连接点表达式:@args(com.david.annotation.validate.Length,*)method={0},args={1},target={2}",

joinPoint.getSignature().getName(),ToStringBuilder.reflectionToString(

joinPoint.getArgs(),ToStringStyle.SHORT_PREFIX_STYLE),joinPoint.getTarget()

.getClass().getName());

}

@Before(value="targetPointcut()")

publicvoidbeforeTarget(JoinPointjoinPoint){

LogUtils

.info(

logger,

"连接点表达式:target(com.david.biz.service.impl.BookServiceImpl)method={0},args={1},target={2}",

joinPoint.getSignature().getName(),ToStringBuilder.reflectionToString(

joinPoint.getArgs(),ToStringStyle.SHORT_PREFIX_STYLE),joinPoint.getTarget()

.getClass().getName());

}

@Before(value="targetAnnotation()")

publicvoidbeforeTargetAnnotation(JoinPointjoinPoint){

LogUtils

.info(

logger,

"连接点表达式:@target(org.springframework.stereotype.Service)method={0},args={1},target={2}",

joinPoint.getSignature().getName(),ToStringBuilder.reflectionToString(

joinPoint.getArgs(),ToStringStyle.SHORT_PREFIX_STYLE),joinPoint.getTarget()

.getClass().getName());

}

}

/** * execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?) *arg() 限制连接点匹配参数为指定类型的执行方法 *@args() 限制连接点匹配参数由执行注解标注的执行 *execution() 用于匹配连接点的执行方法 *this() 限制连接点匹配AOP代理的Bean引用为执行类型的类 *target() 限制连接点匹配目标对象为指定类型的类 *@target() 限制连接点匹配特定的执行对象,这些对象应具备指定的注解类型 *@annotation()限制匹配带有指定注解的连接点 * * * * @author zhangwei_david * @version $Id: LogAspect.java, v 0.1 2014年11月29日 下午1:10:13 zhangwei_david Exp $ */@Component@Aspectpublic class LogAspect { private static final Logger logger = LogManager.getLogger(LogAspect.class); /** * 匹配参数是任何类型,任何数量 且在com,david.biz包或子包下的方法 */ @Pointcut("args(..)&&within(com.david.biz..*)") public void arg() { } @Pointcut("@args(com.david.aop.LoggingRequired)") public void annotationArgs() { } @Pointcut("@annotation(com.david.aop.LoggingRequired)") public void logRequiredPointcut() { } @Pointcut("args(java.lang.String,*)") public void argsWithString() { } @Pointcut("target(com.david.biz.service.impl.BookServiceImpl)") public void targetPointcut() { } @Pointcut("@target(org.springframework.stereotype.Service)") public void targetAnnotation() { } // @Around("execution(* org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(..))") // public Object aa(ProceedingJoinPoint pjp) throws Throwable { // try { // Object retVal = pjp.proceed(); // System.out.println(retVal); // return retVal; // } catch (Exception e) { // System.out.println("异常"); // return null; // } // } @Before(value = "logRequiredPointcut()") public void before(JoinPoint joinPoint) { LogUtils.info(logger, " 连接点表达式@annotation(com.david.aop.LoggingRequired) - method={0} has been visited", joinPoint.getSignature().getName()); } @Before(value = "arg()") public void beforeArg(JoinPoint joinPoint) { LogUtils.info(logger, "连接点表达式:args(..)&&within(com.david.biz..*) method ={0}, args ={1},target={2}", joinPoint.getSignature().getName(), ToStringBuilder.reflectionToString( joinPoint.getArgs(), ToStringStyle.SHORT_PREFIX_STYLE), joinPoint.getTarget() .getClass().getName()); } @Before(value = "argsWithString()") public void beforeArgWithString(JoinPoint joinPoint) { LogUtils.info(logger, "连接点表达式:args(java.lang.String,*) method={0} ,args ={1},target={2}", joinPoint.getSignature().getName(), ToStringBuilder.reflectionToString( joinPoint.getArgs(), ToStringStyle.SHORT_PREFIX_STYLE), joinPoint.getTarget() .getClass().getName()); } @Before(value = "annotationArgs()") public void beforeAnnotationArgs(JoinPoint joinPoint) { LogUtils .info( logger, "连接点表达式:@args(com.david.annotation.validate.Length,*) method={0} ,args ={1},target={2}", joinPoint.getSignature().getName(), ToStringBuilder.reflectionToString( joinPoint.getArgs(), ToStringStyle.SHORT_PREFIX_STYLE), joinPoint.getTarget() .getClass().getName()); } @Before(value = "targetPointcut()") public void beforeTarget(JoinPoint joinPoint) { LogUtils .info( logger, "连接点表达式:target(com.david.biz.service.impl.BookServiceImpl) method={0} ,args ={1},target={2}", joinPoint.getSignature().getName(), ToStringBuilder.reflectionToString( joinPoint.getArgs(), ToStringStyle.SHORT_PREFIX_STYLE), joinPoint.getTarget() .getClass().getName()); } @Before(value = " targetAnnotation()") public void beforeTargetAnnotation(JoinPoint joinPoint) { LogUtils .info( logger, "连接点表达式:@target(org.springframework.stereotype.Service) method={0} ,args ={1},target={2}", joinPoint.getSignature().getName(), ToStringBuilder.reflectionToString( joinPoint.getArgs(), ToStringStyle.SHORT_PREFIX_STYLE), joinPoint.getTarget() .getClass().getName()); }}

Java代码

/**

*

*@authorzhangwei_david

*@version$Id:T.java,v0.12014年12月1日上午9:35:44zhangwei_davidExp$

*/

@RunWith(SpringJUnit4Cla***unner.class)

@ContextConfiguration(locations="file:H:/workspace4study/WebApp/src/main/webapp/WEB-INF/applicationContext.xml")

publicclassBookServiceTest{

@Autowired

privateBookServicebookService;

@Test

publicvoidtestB(){

bookService.addNewBook("JunitTest",1000);

}

}

/** * * @author zhangwei_david * @version $Id: T.java, v 0.1 2014年12月1日 上午9:35:44 zhangwei_david Exp $ */@RunWith(SpringJUnit4Cla***unner.class)@ContextConfiguration(locations = "file:H:/workspace4study/WebApp/src/main/webapp/WEB-INF/applicationContext.xml")public class BookServiceTest { @Autowired private BookService bookService; @Test public void testB() { bookService.addNewBook("Junit Test", 1000); }}

Java代码

2014-12-0111:14:39[main:1577]-[INFO]连接点表达式@annotation(com.david.aop.LoggingRequired)-method=addNewBookhasbeenvisited

2014-12-0111:14:39[main:1587]-[INFO]连接点表达式:args(..)&&within(com.david.biz..*)method=addNewBook,args=Object[][{JunitTest,1000}],target=com.david.biz.service.impl.BookServiceImpl

2014-12-0111:14:39[main:1588]-[INFO]连接点表达式:args(java.lang.String,*)method=addNewBook,args=Object[][{JunitTest,1000}],target=com.david.biz.service.impl.BookServiceImpl

2014-12-0111:14:39[main:1588]-[INFO]连接点表达式:target(com.david.biz.service.impl.BookServiceImpl)method=addNewBook,args=Object[][{JunitTest,1000}],target=com.david.biz.service.impl.BookServiceImpl

2014-12-0111:14:39[main:1589]-[INFO]连接点表达式:@target(org.springframework.stereotype.Service)method=addNewBook,args=Object[][{JunitTest,1000}],target=com.david.biz.service.impl.BookServiceImpl

2014-12-0111:14:39[main:1589]-[INFO]连接点表达式:args(..)&&within(com.david.biz..*)method=insert,args=Object[][{Book[id=0,name=JunitTest,price=1000]}],target=com.david.biz.dao.impl.BookDaoImpl

2014-12-0111:14:39[main:1590]-[INFO]连接点表达式:@args(com.david.annotation.validate.Length,*)method=insert,args=Object[][{Book[id=0,name=JunitTest,price=1000]}],target=com.david.biz.dao.impl.BookDaoImpl

2014-12-0111:14:39[main:1591]-[INFO]连接点表达式:args(java.lang.String,*)method=insert,args=Object[][{demo.insert,Book[id=0,name=JunitTest,price=1000]}],target=com.ibatis.sqlmap.engine.impl.SqlMapClientImpl

2014-12-01 11:14:39 [ main:1577 ] - [ INFO ] 连接点表达式@annotation(com.david.aop.LoggingRequired) - method=addNewBook has been visited2014-12-01 11:14:39 [ main:1587 ] - [ INFO ] 连接点表达式:args(..)&&within(com.david.biz..*) method =addNewBook, args =Object[][{Junit Test,1000}],target=com.david.biz.service.impl.BookServiceImpl2014-12-01 11:14:39 [ main:1588 ] - [ INFO ] 连接点表达式:args(java.lang.String,*) method=addNewBook ,args =Object[][{Junit Test,1000}],target=com.david.biz.service.impl.BookServiceImpl2014-12-01 11:14:39 [ main:1588 ] - [ INFO ] 连接点表达式:target(com.david.biz.service.impl.BookServiceImpl) method=addNewBook ,args =Object[][{Junit Test,1000}],target=com.david.biz.service.impl.BookServiceImpl2014-12-01 11:14:39 [ main:1589 ] - [ INFO ] 连接点表达式:@target(org.springframework.stereotype.Service) method=addNewBook ,args =Object[][{Junit Test,1000}],target=com.david.biz.service.impl.BookServiceImpl2014-12-01 11:14:39 [ main:1589 ] - [ INFO ] 连接点表达式:args(..)&&within(com.david.biz..*) method =insert, args =Object[][{Book[id=0,name=Junit Test,price=1000]}],target=com.david.biz.dao.impl.BookDaoImpl2014-12-01 11:14:39 [ main:1590 ] - [ INFO ] 连接点表达式:@args(com.david.annotation.validate.Length,*) method=insert ,args =Object[][{Book[id=0,name=Junit Test,price=1000]}],target=com.david.biz.dao.impl.BookDaoImpl2014-12-01 11:14:39 [ main:1591 ] - [ INFO ] 连接点表达式:args(java.lang.String,*) method=insert ,args =Object[][{demo.insert,Book[id=0,name=Junit Test,price=1000]}],target=com.ibatis.sqlmap.engine.impl.SqlMapClientImpl

萌萌的IT人