SpringAOP的几种配置
来源:互联网 发布:java用sleep内存泄露 编辑:程序博客网 时间:2024/06/05 03:57
Spring实现AOP其实本质是有两种方式.
- 1 基于XML配置的方式,
基于XML的方式又细分为两种
- 基于代理实现的AOP
- 纯pojo切面,基于SpringAop容器实现的
- 2 基于注解的方式
现在就来说基于XML形式的第一种:基于代理模式的实现.
如果说我们要实现aop通知的那个类实现的有其他接口的话,那么使用的代理模式就是JDK自带的动态代理模式,无实现接口的话是用CGIB动态代理模式.
这里使用有实现接口的业务类.上代码,
- (1)可睡觉的接口,任何可以睡觉的人或机器都可以实现它
public interface Sleepable { public void sleep(); }
- (2)接口实现类,“Me”可以睡觉,“Me”就实现可以睡觉的接口。
public class Me implements Sleepable{ public void sleep() { System.out.println("\n睡觉!不休息哪里有力气学习!\n"); } }
- (3)Me关注于睡觉的逻辑,但是睡觉需要其他功能辅助,比如睡前脱衣服,起床脱衣服,这里开始就需要AOP替“Me”完成!解耦!首先需要一个SleepHelper(切面类)类。因为一个是切入点前执行、一个是切入点之后执行,所以实现对应接口(这是与另外一种XML方式区别的地方,纯pojo,Spring容器实现的方法,切面类没有实现这些接口)。
public class SleepHelper implements MethodBeforeAdvice, AfterReturningAdvice { public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable { System.out.println("睡觉前要脱衣服!"); } public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable { System.out.println("起床后要穿衣服!"); } }
- (4)Spring核心配置文件application.xml配置AOP。
<!-- 定义被代理者 --> <bean id="me" class="com.springAOP.bean.Me"></bean> <!-- 定义通知内容,也就是切入点执行前后需要做的事情 --> <bean id="sleepHelper" class="com.springAOP.bean.SleepHelper"></bean> <!-- 定义切入点位置 --> <bean id="sleepPointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut"> <property name="pattern" value=".*sleep"></property> </bean> <!-- 使切入点与通知相关联,完成切面配置 --> <bean id="sleepHelperAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor"> <property name="advice" ref="sleepHelper"></property> <property name="pointcut" ref="sleepPointcut"></property> </bean> <!-- 设置代理 --> <bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <!-- 代理的对象,有睡觉能力 --> <property name="target" ref="me"></property> <!-- 使用切面 --> <property name="interceptorNames" value="sleepHelperAdvisor"></property> <!-- 代理接口,睡觉接口 --> <property name="proxyInterfaces" value="com.springAOP.bean.Sleepable"></property> </bean> </beans>
现在就来说基于XML形式的第二种:
- (1)修改后的SleepHelper类,很正常的类,所以这种方式的优点就是在代码中不体现任何AOP相关配置,纯粹使用xml配置。
public class SleepHelper{ public void beforeSleep(){ System.out.println("睡觉前要脱衣服!"); } public void afterSleep(){ System.out.println("睡醒了要穿衣服!"); } }
- (2) 业务类不做修改
- (3)配置文件:
<!-- 定义通知内容,也就是切入点执行前后需要做的事情 --> <bean id="sleepHelper" class="com.springAOP.bean.SleepHelper"></bean> <!-- 定义被代理者 --> <bean id="me" class="com.springAOP.bean.Me"></bean> <aop:config> <aop:aspect ref="sleepHelper"> <aop:before method="beforeSleep" pointcut="execution(* *.sleep(..))" /> <aop:after method="afterSleep" pointcut="execution(* *.sleep(..))" /> </aop:aspect> </aop:config> </beans>
- (4)测试 ,结果一致.
基于注解实现的方式
这种方式简单,代码简洁.
- (1)同样的例子,修改后的SleepHelper:
/** * @Aspect * 定义这个类为切面类 */@Aspect public class SleepHelper{ public SleepHelper(){ } /** * @Pointcut("execution(* *.sleep())") * 定义这个方法为切入点,括号里面是execution()表达式 * 表示切入到的位置为-->返回值为任何形式,任何包的任何类的sleep()方法上. * 注意是无参的 * */ @Pointcut("execution(* *.sleep())") public void sleeppoint(){} /** * @Before("sleeppoint()") * 定义这个方法作为前置通知. * 并在sleeppoint()所指定的切点上执行这个前置通知 */ @Before("sleeppoint()") public void beforeSleep(){ System.out.println("睡觉前要脱衣服!"); } @AfterReturning("sleeppoint()") public void afterSleep(){ System.out.println("睡醒了要穿衣服!"); } }
- (3)然后修改配置为:
<!-- 开启支持@AspectJ风格的切面声明 --> <aop:aspectj-autoproxy /> <!-- 定义通知内容,也就是切入点执行前后需要做的事情 --> <bean id="sleepHelper" class="com.springAOP.bean.SleepHelper"></bean> <!-- 定义被代理者 --> <bean id="me" class="com.springAOP.bean.Me"></bean>
- (4)最后测试,一样的结果!
PS:
@Component注解
如果切面类上除了@Aspect注解外还加上一个@Component注解,那么XML配置就不用写
<bean id="" class=""> </bean>
之类的bean组件.但是XML需要加入扫描注解的配置:
<context:component-scan base-package="com.qiushiju"> <!-- 扫描包括这些路径下的类 --> <context:include-filter type="annotation" expression=""/> <!-- 告诉主容器不要扫描加有@Controller 这些类,这些bean 是由web容器进行管理的 --> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" /> </context:component-scan>
因为@Component注解就是声明这个类是Spring容器托管的类,会扫描到自动加载的.与@Controller @Service @Repository功能一样.
@Pointcut(@annotation)注解
@Pointcut(@annotation)与 @Pointcut(“execution(* .(..)”)的区别
@Pointcut(“execution(* .(..)”)是在指定的返回参数类型,指定路径的指定方法上切入进行各种通知操作,如上面的代码.
@Pointcut(@annotation)是适用于自定义注解的情况.我自定义一个一个注解类
@Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface MyLog { /** * 日志描述 */ String desc() default ""; /** * 操作表类型 */ int type() default ""; }
如果要在这个注解所在的方法(一般是Controller层的方法上)使用AOP的通知操作(一般做日志处理),那就把这个注解类定义为切点.即在切面类中定义切点的时候使用@Pointcut(@annotation)方式声明
@Pointcut("@annotation(com.qiushiju.demo.common.annotion.log.MyLog)") public void cutService() { }
这样在调用加了@MyLog注解的controller层方法时,@MyLog最为切入点,那么这个方法在执行前就会被SpringAop所拦截,并首先执行切面类中定义的各种通知方法,比如前置通知,异常通知等.然后再执行controller层的方法,之后还会执行Aop的后置通知,当然是你配置了后置通知的前提下…
@Controller的controller层不能被AOP拦截的问题
因为controller被JDK的动态代理代理了,所以配置文件中就应该设置成强制使用CGLB代理,配置文件如下
<!--通知spring使用cglib而不是jdk的来生成代理方法 AOP可以拦截到Controller-> <aop:aspectj-autoproxy proxy-target-class="true" />
利用Aop注解做日志管理
http://blog.csdn.net/czmchen/article/details/42392985
需要的类:一个log实体类/log注解类/aop类.在aop类里面进行Log的具体操作,比如进行持久化的功能等.可以实现拦截controller层和service层的方法进行做日志记录.
- SpringAOP的几种配置
- springAOP的两种配置方法
- springAOP的配置及实例
- SpringAOP的五种通知的配置及使用
- springAOP配置
- SpringAOP配置
- SpringAOP对于事物的配置的一种
- SpringAOP配置事务
- springAop基于注解配置
- springAOP基于xml的配置前后环绕通知
- Spring声明式事务配置的两种策略SpringAop和Bean后处理器的代理BeanNameAutoProxyCreator
- SpringAOP的实现
- 基于注解的SpringAOP
- SpringAop的使用
- SpringAop的相关概念
- springAop遇到的问题
- springAOP的入门例子
- springAOP的注解
- springboot访问html文件
- Visual Studio Code创建C#项目
- 图像bayer格式介绍以及bayer插值原理CFA
- 教你开发jQuery插件
- bcache ssd hdd
- SpringAOP的几种配置
- cloudera Manager 配置报警邮箱
- 程序中打印的
- phantomjs 简介
- 一步一图搭建-分布式服务器部署之mysql集群-主从复制与读写分离
- C++集合的模板类 交并集
- 11.3 欢乐爆零赛 知识总结 (Hanoi Rank Tree )
- 数组遍历
- 稳定性、防故障方法论