spring中aop全注解时配置类怎么写

spring中aop全注解时配置类怎么写,第1张

先说注解,使用注解配置Spring AOP总体分为两步,第一步是在xml文件中声明激活自动扫描组件功能,同时激活自动代理功能(同时在xml中添加一个UserService的普通服务层组件,来测试AOP的注解功能):

<xml version="10" encoding="UTF-8">

<beans xmlns=">

第二步是为Aspect切面类添加注解:

package cnyshstudiospringaopaspect;

import orgapachecommonsloggingLog;

import orgapachecommonsloggingLogFactory;

import orgaspectjlangJoinPoint;

import orgaspectjlangProceedingJoinPoint;

import orgaspectjlangannotationAfter;

import orgaspectjlangannotationAfterReturning;

import orgaspectjlangannotationAfterThrowing;

import orgaspectjlangannotationAround;

import orgaspectjlangannotationAspect;

import orgaspectjlangannotationBefore;

import orgaspectjlangannotationPointcut;

import orgspringframeworkstereotypeComponent;

/

系统服务组件Aspect切面Bean

@author Shenghany

@date 2013-5-28

/

//声明这是一个组件

@Component

//声明这是一个切面Bean

@Aspect

public class ServiceAspect {

private final static Log log = LogFactorygetLog(ServiceAspectclass);

//配置切入点,该方法无方法体,主要为方便同类中其他方法使用此处配置的切入点

@Pointcut("execution( cnyshstudiospringaopservice())")

public void aspect(){ }

/

配置前置通知,使用在方法aspect()上注册的切入点

同时接受JoinPoint切入点对象,可以没有该参数

/

@Before("aspect()")

public void before(JoinPoint joinPoint){

if(logisInfoEnabled()){

loginfo("before " + joinPoint);

}

}

//配置后置通知,使用在方法aspect()上注册的切入点

@After("aspect()")

public void after(JoinPoint joinPoint){

if(logisInfoEnabled()){

loginfo("after " + joinPoint);

}

}

//配置环绕通知,使用在方法aspect()上注册的切入点

@Around("aspect()")

public void around(JoinPoint joinPoint){

long start = SystemcurrentTimeMillis();

try {

((ProceedingJoinPoint) joinPoint)proceed();

long end = SystemcurrentTimeMillis();

if(logisInfoEnabled()){

loginfo("around " + joinPoint + "\tUse time : " + (end - start) + " ms!");

}

} catch (Throwable e) {

long end = SystemcurrentTimeMillis();

if(logisInfoEnabled()){

loginfo("around " + joinPoint + "\tUse time : " + (end - start) + " ms with exception : " + egetMessage());

}

}

}

//配置后置返回通知,使用在方法aspect()上注册的切入点

@AfterReturning("aspect()")

public void afterReturn(JoinPoint joinPoint){

if(logisInfoEnabled()){

loginfo("afterReturn " + joinPoint);

}

}

//配置抛出异常后通知,使用在方法aspect()上注册的切入点

@AfterThrowing(pointcut="aspect()", throwing="ex")

public void afterThrow(JoinPoint joinPoint, Exception ex){

if(logisInfoEnabled()){

loginfo("afterThrow " + joinPoint + "\t" + exgetMessage());

}

}

}

测试代码:

package cnyshstudiospringaop;

import orgapachecommonsloggingLog;

import orgapachecommonsloggingLogFactory;

import orgspringframeworkcontextApplicationContext;

import orgspringframeworkcontextsupportClassPathXmlApplicationContext;

import cnyshstudiospringaopserviceUserService;

import cnyshstudiospringmvcbeanUser;

/

Spring AOP测试

@author Shenghany

@date 2013-5-28

/

public class Tester {

private final static Log log = LogFactorygetLog(Testerclass);

public static void main(String[] args) {

//启动Spring容器

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContextxml");

//获取service组件

UserService service = (UserService) contextgetBean("userService");

//以普通的方式调用UserService对象的三个方法

User user = serviceget(1L);

servicesave(user);

try {

servicedelete(1L);

} catch (Exception e) {

if(logisWarnEnabled()){

logwarn("Delete user : " + egetMessage());

}

}

}

}

控制台输出如下:

INFO [springaopaspectServiceAspect:40] before execution(User cnyshstudiospringaopserviceUserServiceget(long))

INFO [springaopserviceUserService:19] getUser method

INFO [springaopaspectServiceAspect:60] around execution(User cnyshstudiospringaopserviceUserServiceget(long)) Use time : 42 ms!

INFO [springaopaspectServiceAspect:48] after execution(User cnyshstudiospringaopserviceUserServiceget(long))

INFO [springaopaspectServiceAspect:74] afterReturn execution(User cnyshstudiospringaopserviceUserServiceget(long))

INFO [springaopaspectServiceAspect:40] before execution(void cnyshstudiospringaopserviceUserServicesave(User))

INFO [springaopserviceUserService:26] saveUser method

INFO [springaopaspectServiceAspect:60] around execution(void cnyshstudiospringaopserviceUserServicesave(User)) Use time : 2 ms!

INFO [springaopaspectServiceAspect:48] after execution(void cnyshstudiospringaopserviceUserServicesave(User))

INFO [springaopaspectServiceAspect:74] afterReturn execution(void cnyshstudiospringaopserviceUserServicesave(User))

INFO [springaopaspectServiceAspect:40] before execution(boolean cnyshstudiospringaopserviceUserServicedelete(long))

INFO [springaopserviceUserService:32] delete method

INFO [springaopaspectServiceAspect:65] around execution(boolean cnyshstudiospringaopserviceUserServicedelete(long)) Use time : 5 ms with exception : spring aop ThrowAdvice演示

INFO [springaopaspectServiceAspect:48] after execution(boolean cnyshstudiospringaopserviceUserServicedelete(long))

INFO [springaopaspectServiceAspect:74] afterReturn execution(boolean cnyshstudiospringaopserviceUserServicedelete(long))

WARN [studiospringaopTester:32] Delete user : Null return value from advice does not match primitive return type for: public boolean cnyshstudiospringaopserviceUserServicedelete(long) throws javalangException

可以看到,正如我们预期的那样,虽然我们并没有对UserSerivce类包括其调用方式做任何改变,但是Spring仍然拦截到了其中方法的调用,或许这正是AOP的魔力所在。

再简单说一下xml配置方式,其实也一样简单:

<xml version="10" encoding="UTF-8">

<beans xmlns=">

个人觉得不如注解灵活和强大,你可以不同意这个观点,但是不知道如下的代码会不会让你的想法有所改善:

//配置前置通知,拦截返回值为cnyshstudiospringmvcbeanUser的方法

@Before("execution(cnyshstudiospringmvcbeanUser cnyshstudiospringaopservice())")

public void beforeReturnUser(JoinPoint joinPoint){

if(logisInfoEnabled()){

loginfo("beforeReturnUser " + joinPoint);

}

}

//配置前置通知,拦截参数为cnyshstudiospringmvcbeanUser的方法

@Before("execution( cnyshstudiospringaopservice(cnyshstudiospringmvcbeanUser))")

public void beforeArgUser(JoinPoint joinPoint){

if(logisInfoEnabled()){

loginfo("beforeArgUser " + joinPoint);

}

}

//配置前置通知,拦截含有long类型参数的方法,并将参数值注入到当前方法的形参id中

@Before("aspect()&&args(id)")

public void beforeArgId(JoinPoint joinPoint, long id){

if(logisInfoEnabled()){

loginfo("beforeArgId " + joinPoint + "\tID:" + id);

}

}

附上UserService的代码(其实很简单):

package cnyshstudiospringaopservice;

import orgapachecommonsloggingLog;

import orgapachecommonsloggingLogFactory;

import cnyshstudiospringmvcbeanUser;

/

用户服务模型

@author Shenghany

@date 2013-5-28

/

public class UserService {

private final static Log log = LogFactorygetLog(UserServiceclass);

public User get(long id){

if(logisInfoEnabled()){

loginfo("getUser method ");

}

return new User();

}

public void save(User user){

if(logisInfoEnabled()){

loginfo("saveUser method ");

}

}

public boolean delete(long id) throws Exception{

if(logisInfoEnabled()){

loginfo("delete method ");

throw new Exception("spring aop ThrowAdvice演示");

}

return false;

}

}

应该说学习Spring AOP有两个难点,第一点在于理解AOP的理念和相关概念,第二点在于灵活掌握和使用切入点表达式。概念的理解通常不在一朝一夕,慢慢浸泡的时间长了,自然就明白了,下面我们简单地介绍一下切入点表达式的配置规则吧。

通常情况下,表达式中使用”execution“就可以满足大部分的要求。表达式格式如下:

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

modifiers-pattern:方法的 *** 作权限

ret-type-pattern:返回值

declaring-type-pattern:方法所在的包

name-pattern:方法名

parm-pattern:参数名

throws-pattern:异常

其中,除ret-type-pattern和name-pattern之外,其他都是可选的。上例中,execution( comspringservice())表示comspringservice包下,返回值为任意类型;方法名任意;参数不作限制的所有方法。

最后说一下通知参数

可以通过args来绑定参数,这样就可以在通知(Advice)中访问具体参数了。例如,<aop:aspect>配置如下:

<aop:config>

<aop:aspect id="TestAspect" ref="aspectBean">

<aop:pointcut id="businessService"

expression="execution( comspringservice(String,)) and args(msg,)" />

<aop:after pointcut-ref="businessService" method="doAfter"/>

</aop:aspect>

</aop:config>上面的代码args(msg,)是指将切入点方法上的第一个String类型参数添加到参数名为msg的通知的入参上,这样就可以直接使用该参数啦。

全称也不说了,字面意思就是面向方面编程。举一个最普遍的例子,就是如果我们代码需要做日志的话,那么在没有AOP的时候,我们的代码可能就是这样:

public class A{

public void methodA(){

do log;

bmethodB();

}

}

这里methodA()中的做日志并不是方法本身的逻辑功能,而是一个附属功能,因此,我们需要把它分离出去。怎么分离,就是AOP要做的事情,简单来说,就是系统在调用者不知情的情况下,为我们的类A增加了一个代理类,她把我们的类A包装了起来,像这样:

public class AP extends A{

A a;

public void methodA(){

do log;

amethodA():

}

}

public class A{

public void methodA(){

bmethodB();

}

}

于是,当我们以为自己在调用A的methodA()方法时,实际调用的将是AP中的methodA(),于是就可以把做日志的功能从原有的methodA()中分离了出去。所以,AOP要做的就是在用户不知道的情况下,将我们的调用点包裹了起来,从而把原来的功能进行了分离。

@RequestMapping(value = "/login", method = RequestMethodGET)

public ModelAndView myMethod(>

以上就是关于spring中aop全注解时配置类怎么写全部的内容,包括:spring中aop全注解时配置类怎么写、请举例对比说明什么是AOP、aop怎么获取springmvc controller中的requestmapping等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/10067760.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-04
下一篇 2023-05-04

发表评论

登录后才能评论

评论列表(0条)

保存