spring 代理注解 <aop:aspectj-autoproxy />
spring默认使用jdk的代理方式,
使用jdk的代理方式我们知道,代理的类需要实现一个接口,若果没有就会报,java.lang.NoSuchMethodException: com.sun.proxy.$Proxy83.loginPage()异常,
这时候我们可以使用<aop:aspectj-autoproxy proxy-target-class="true"/>让spring使用cglib的代理方式,
cglib的时候需要有默认的构造方法,class不能为final的,
如果你对项目中的action就是contorller层代理这就会报这个异常,因为contorller这层没有实现接口,
我们使用<aop:aspectj-autoproxy proxy-target-class="false"/>来指定让他来使用cglib的代理方式,但是: Could not generate CGLIB subclass of class [class com.sun.proxy.$Proxy22]: Common causes of this problem include using a final class or a non-visible class; 可能会报这个异常,它的意思不能代理final的或后类,我觉的这个是使用的baseDaoImpl的问题,全部继承了basedaoImpl在这个里面使用了
ParameterizedType pt = (ParameterizedType) this.getClass()
.getGenericSuperclass();
this.clazz = (Class<T>) pt.getActualTypeArguments()[0];
Caused by: net.sf.cglib.core.CodeGenerationException: java.lang.ClassCastException-->java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
需要这个类不实现接口,
解决方案值配置<aop:aspectj-autoproxy /> 现在发现应该是spring会自动在JDK动态代理和CGLIB之间转换。
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Spring除了支持Schema方式配置AOP,还支持注解方式:使用@AspectJ风格的切面声明。
1 启用对@AspectJ的支持
Spring默认不支持@AspectJ风格的切面声明,为了支持需要使用如下配置:
java代码:
<aop:aspectj-autoproxy/>
这样Spring就能发现@AspectJ风格的切面并且将切面应用到目标对象。
2 声明切面
@AspectJ风格的声明切面非常简单,使用@Aspect注解进行声明:
java代码:
@Aspect()
Public class Aspect{
……
}
然后将该切面在配置文件中声明为Bean后,Spring就能自动识别并进行AOP方面的配置:
java代码:
<bean id="aspect" class="……Aspect"/>
该切面就是一个POJO,可以在该切面中进行切入点及通知定义,接着往下看吧。
3 声明切入点
@AspectJ风格的命名切入点使用org.aspectj.lang.annotation包下的@Pointcut+方法(方法必须是返回void类型)实现。
java代码:
@Pointcut(value="切入点表达式", argNames = "参数名列表")
public void pointcutName(……) {}
value:指定切入点表达式;
argNames:指定命名切入点方法参数列表参数名字,可以有多个用“,”分隔,这些参数将传递给通知方法同名的参数,同时比如切入点表达式“args(param)”将匹配参数类型为命名切入点方法同名参数指定的参数类型。
pointcutName:切入点名字,可以使用该名字进行引用该切入点表达式。
java代码:
查看复制到剪贴板打印
@Pointcut(value="execution(* cn.javass..*.sayAdvisorBefore(..)) && args(param)", argNames = "param")
public void beforePointcut(String param) {}
定义了一个切入点,名字为“beforePointcut”,该切入点将匹配目标方法的第一个参数类型为通知方法实现中参数名为“param”的参数类型。
4 声明通知
@AspectJ风格的声明通知也支持5种通知类型:
一、前置通知:使用org.aspectj.lang.annotation 包下的@Before注解声明;
java代码:
@Before(value = "切入点表达式或命名切入点", argNames = "参数列表参数名")
value:指定切入点表达式或命名切入点;
argNames:与Schema方式配置中的同义。
接下来示例一下吧:
1、定义接口和实现,在此我们就使用Schema风格时的定义;
2、定义切面:
java代码:
查看复制到剪贴板打印
package cn.javass.spring.chapter6.aop;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class HelloWorldAspect2 {
}
3、定义切入点:
java代码:
@Pointcut(value="execution(* cn.javass..*.sayAdvisorBefore(..)) && args(param)", argNames = "param")
public void beforePointcut(String param) {}
4、定义通知:
java代码:
查看复制到剪贴板打印
@Before(value = "beforePointcut(param)", argNames = "param")
public void beforeAdvice(String param) {
System.out.println("===========before advice param:" + param);
}
5、在chapter6/advice2.xml配置文件中进行如下配置:
java代码:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<aop:aspectj-autoproxy/>
<bean id="helloWorldService"
class="cn.javass.spring.chapter6.service.impl.HelloWorldService"/>
<bean id="aspect"
class="cn.javass.spring.chapter6.aop.HelloWorldAspect2"/>
</beans>
6、测试代码cn.javass.spring.chapter6.AopTest:
java代码:
@Test
public void testAnnotationBeforeAdvice() {
System.out.println("======================================");
ApplicationContext ctx = new ClassPathXmlApplicationContext("chapter6/advice2.xml");
IHelloWorldService helloworldService = ctx.getBean("helloWorldService", IHelloWorldService.class);
helloworldService.sayBefore("before");
System.out.println("======================================");
}
将输出:
==========================================
===========before advice param:before
============say before
==========================================
切面、切入点、通知全部使用注解完成:
1)使用@Aspect将POJO声明为切面;
2)使用@Pointcut进行命名切入点声明,同时指定目标方法第一个参数类型必须是java.lang.String,对于其他匹配的方法但参数类型不一致的将也是不匹配的,通过argNames = "param"指定了将把该匹配的目标方法参数传递给通知同名的参数上;
3)使用@Before进行前置通知声明,其中value用于定义切入点表达式或引用命名切入点;
4)配置文件需要使用<aop:aspectj-autoproxy/>来开启注解风格的@AspectJ支持;
5)需要将切面注册为Bean,如“aspect”Bean;
6)测试代码完全一样。
二、后置返回通知:使用org.aspectj.lang.annotation 包下的@AfterReturning注解声明;
java代码:
@AfterReturning(
value="切入点表达式或命名切入点",
pointcut="切入点表达式或命名切入点",
argNames="参数列表参数名",
returning="返回值对应参数名")
value:指定切入点表达式或命名切入点;
pointcut:同样是指定切入点表达式或命名切入点,如果指定了将覆盖value属性指定的,pointcut具有高优先级;
argNames:与Schema方式配置中的同义;
returning:与Schema方式配置中的同义。
java代码:
@AfterReturning(
value="execution(* cn.javass..*.sayBefore(..))",
pointcut="execution(* cn.javass..*.sayAfterReturning(..))",
argNames="retVal", returning="retVal")
public void afterReturningAdvice(Object retVal) {
System.out.println("===========after returning advice retVal:" + retVal);
}
其中测试代码与Schema方式几乎一样,在此就不演示了,如果需要请参考AopTest.java中的testAnnotationAfterReturningAdvice测试方法。
三、后置异常通知:使用org.aspectj.lang.annotation 包下的@AfterThrowing注解声明;
java代码:
@AfterThrowing (
value="切入点表达式或命名切入点",
pointcut="切入点表达式或命名切入点",
argNames="参数列表参数名",
throwing="异常对应参数名")
value:指定切入点表达式或命名切入点;
pointcut:同样是指定切入点表达式或命名切入点,如果指定了将覆盖value属性指定的,pointcut具有高优先级;
argNames:与Schema方式配置中的同义;
throwing:与Schema方式配置中的同义。
java代码:
@AfterThrowing(
value="execution(* cn.javass..*.sayAfterThrowing(..))",
argNames="exception", throwing="exception")
public void afterThrowingAdvice(Exception exception) {
System.out.println("===========after throwing advice exception:" + exception);
}
其中测试代码与Schema方式几乎一样,在此就不演示了,如果需要请参考AopTest.java中的testAnnotationAfterThrowingAdvice测试方法。
四、后置最终通知:使用org.aspectj.lang.annotation 包下的@After注解声明;
java代码:
@After (
value="切入点表达式或命名切入点",
argNames="参数列表参数名")
value:指定切入点表达式或命名切入点;
argNames:与Schema方式配置中的同义;
java代码:
@After(value="execution(* cn.javass..*.sayAfterFinally(..))")
public void afterFinallyAdvice() {
System.out.println("===========after finally advice");
}
其中测试代码与Schema方式几乎一样,在此就不演示了,如果需要请参考AopTest.java中的testAnnotationAfterFinallyAdvice测试方法。
五、环绕通知:使用org.aspectj.lang.annotation 包下的@Around注解声明;
java代码:
@Around (
value="切入点表达式或命名切入点",
argNames="参数列表参数名")
value:指定切入点表达式或命名切入点;
argNames:与Schema方式配置中的同义;
java代码:
@Around(value="execution(* cn.javass..*.sayAround(..))")
public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("===========around before advice");
Object retVal = pjp.proceed(new Object[] {"replace"});
System.out.println("===========around after advice");
return retVal;
}
其中测试代码与Schema方式几乎一样,在此就不演示了,如果需要请参考AopTest.java中的annotationAroundAdviceTest测试方法。
6.4.5 引入
@AspectJ风格的引入声明在切面中使用org.aspectj.lang.annotation包下的@DeclareParents声明:
java代码:
@DeclareParents(
value=" AspectJ语法类型表达式",
defaultImpl=引入接口的默认实现类)
private Interface interface;
value:匹配需要引入接口的目标对象的AspectJ语法类型表达式;与Schema方式中的types-matching属性同义;
private Interface interface:指定需要引入的接口;
defaultImpl:指定引入接口的默认实现类,没有与Schema方式中的delegate-ref属性同义的定义方式;
java代码:
@DeclareParents(
value="cn.javass..*.IHelloWorldService+", defaultImpl=cn.javass.spring.chapter6.service.impl.IntroductiondService.class)
private IIntroductionService introductionService;
其中测试代码与Schema方式几乎一样,在此就不演示了,如果需要请参考AopTest.java中的testAnnotationIntroduction测试方法。
---------------------
spring 代理注解 <aop:aspectj-autoproxy />的更多相关文章
- spring的注解AOP配置
package com.hope.service.impl;import com.hope.service.IAccountService;import org.aspectj.lang.annota ...
- Spring——代理实现AOP
一.静态代理实现 1.接口(抽象主题) 2.接口的实现类(真实主题) 3.代理类(代理主题) 4.测试类: ApplicationContext context=new ClassPathXmlApp ...
- 【Redis】redis异步消息队列+Spring自定义注解+AOP方式实现系统日志持久化
说明: SSM项目中的每一个请求都需要进行日志记录操作.一般操作做的思路是:使用springAOP思想,对指定的方法进行拦截.拼装日志信息实体,然后持久化到数据库中.可是仔细想一下会发现:每次的客户端 ...
- 阶段3 2.Spring_08.面向切面编程 AOP_9 spring基于注解的AOP配置
复制依赖和改jar包方式 src下的都复制过来. 复制到新项目里了 bean.xml里面复制上面一行代码到下面.把aop改成context. 配置spring容器创建时要扫描的包 Service的配置 ...
- Spring中的AOP 专题
Caused by: java.lang.IllegalArgumentException: ProceedingJoinPoint is only supported for around advi ...
- Spring框架之AOP源码完全解析
Spring框架之AOP源码完全解析 Spring可以说是Java企业开发里最重要的技术.Spring两大核心IOC(Inversion of Control控制反转)和AOP(Aspect Orie ...
- Java AOP nested exception is java.lang.NoClassDefFoundError: org/aopalliance/aop/Advice || Error creating bean with name 'org.springframework.aop.aspectj.AspectJPointcutAdvisor#0' 两个异常解决办法
贴出applicationContext.xml <?xml version="1.0" encoding="UTF-8"?> <beans ...
- 8 -- 深入使用Spring -- 4...6 AOP代理:基于注解的XML配置文件的管理方式
8.4.6 基于XML配置文件的管理方式 Spring 2.x 提供一个新的aop:命名空间来定义切面.切入点和增强处理. XML配置方式优点: ⊙ 如果应用没有使用JDK 1.5 以上版本,那么应用 ...
- 8 -- 深入使用Spring -- 4...5 AOP代理:基于注解的“零配置”方式
8.4.5 基于注解的“零配置”方式 AspectJ允许使用注解定义切面.切入点和增强处理,而Spring框架则可识别并根据这些注解来生成AOP代理.Spring只是使用了和AspectJ 5 一样的 ...
随机推荐
- 关于php中的exec命令
这个命令 一般是被禁用的 一些特殊需求的时刻 可以启用 比如 调用系统上的一些数据或者命令 $command ='/www/wwwroot/t.6328.net/Public/cfile/test' ...
- 14.纯 CSS 创作一种侧立图书的特效
原文地址:https://segmentfault.com/a/1190000014751037 HTML代码: <div class="books"> <div ...
- (1)Linux操作系统的安装
1.安装Vmware Workstation 如何判断Vmware是否安装成功? 我的电脑控制面板 --> 网络和Internet --> 查看网络状态和任务 --> 更改适配器设置 ...
- bash-4.2$ bash: /home/test/.bashrc: 权限不够
解决办法:https://blog.csdn.net/qq_38417808/article/details/81705559
- 国内好的python学习地址
python3官方在线文档https://docs.python.org/3/ 玩蛇网http://www.iplaypy.com/ python中文网 http://bbs.pythontab.co ...
- MFC 如何在一个类中使用在其他类中定义的变量或函数
[声明:本文的知识点来源于网络,参考网址:https://blog.csdn.net/bill_ming/article/details/7407848] [以下三种方法亲测有效,可以根据具体情况来选 ...
- xml文件中的${}
看到了${}这样的表达式,脑海里面第一印象是不是我们jsp中的EL表达式?! 哈哈... 不过,这个真不是EL表达式,Spring提供了自己的EL表达式,可是它的格式是#{} so.... ${key ...
- Mybatis:通过MapperScannerConfigurer进行mapper扫描
在applicationContext.xml里配置的
- url查询参数解析
url查询参数解析 1.获取url的各部分值 举例http://i.cnblogs.com/EditPosts.aspx?opt=1 1.window.location.href(设置或获取整个 UR ...
- <基础> PHP 进阶之 类(Class)
属性 类的变量成员叫做“属性”,或者叫“字段”.“特征”,在本文档统一称为“属性”.属性声明是由关键字 public,protected 或者 private 开头,然后跟一个普通的变量声明来组成.属 ...