17-spring学习-AOP初步实现
AOP是面向方面的编程,在实际开发中,AOP都会工作在业务层,因为业务层要调用数据层,而业务层也要完成所有辅助性的业务层操作。
范例:定义业务层操作接口:
package com.Spring.Service;
import com.Spring.Vo.Member; public interface IMemberService { public Boolean insert(Member vo);
}
实现操作接口:
package com.Spring.Service.Impl;
import org.springframework.stereotype.Service;
import com.Spring.Service.IMemberService;
import com.Spring.Vo.Member; @Service
public class IMemberServiceImpl implements IMemberService { @Override
public Boolean insert(Member vo) {
System.out.println("数据层调用 Member="+vo);
return false;
}
}
此时的业务层只关兴核心的业务功能,核心的功能就是调用了业务层代码。
随后所有的辅助性操作功能,都通过spring容器,动态配置。
范例:为项目配置Annotation的扫描支持:
base-package:表示扫描com.spring开头的包以下的文件,配合@Service注解,这个包以下的相关类会自动配置,代替一般的bean配置。
可以复习:http://www.cnblogs.com/alsf/p/7968072.html
<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd"> <context:annotation-config/>
<context:component-scan base-package="com.Spring"/> </beans>
测试代码:
package com.Spring.Test; import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import com.Spring.Service.IMemberService;
import com.Spring.Service.Impl.MemberServiceImpl;
import com.Spring.Vo.Member; public class TestMemberService { public static void main(String args[])
{
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
IMemberService ser=ctx.getBean("memberServiceImpl",MemberServiceImpl.class);
Member vo=new Member();
vo.setMid("hello");
vo.setName("你好");
System.out.println(ser.insert(vo));
}
}
输出结果:
但是这种操作并不严格,还需要准备相应的辅助性功能,那么这些辅助性的功能,可以单独定义在一个切面处理的类之中。
范例:定义切面处理类。
这里的切面类也用@Component做annotation配置,applicationcontext.xml文件里使用的时候直接使用serviceAspect就行了。
package com.Spring.aop; import org.springframework.stereotype.Component; @Component
public class ServiceAspect { public void serviceBefore()
{
System.out.println("AOP切面执行日志记录操作");
} public void serviceAfter()
{
System.out.println("AOP切面执行事务处理操作");
}
}
默认情况下spring不会开启切面。引入AOP命名空间。
范例:修改applicationContext.xml文件
勾选上:

代码中多了这些:

下面在XML文件中配置文件组织切面。
范例:定义切面引用
<aop:config>
<!-- 定义程序的切入点,这里exucution表示对哪个包下面的类进行切入 -->
<aop:pointcut expression="execution(* com.Spring..*.*(..)))" id="pointcut"/>
<!-- 这里ref的对象是通过annotation配置@Component出来的, -->
<!-- 定义面向方面的处理类 -->
<aop:aspect ref="serviceAspect">
<!--aop:before和aop:xx 里面需要pointcut-ref,表示依赖哪个切入点。-->
<aop:before method="serviceBefore" pointcut-ref="pointcut"/>
<aop:after method="serviceAfter" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>
重新执行最开始的Test类,发现报错:
Bean named 'memberServiceImpl' must be of type [com.Spring.Service.Impl.MemberServiceImpl], but was actually of type [com.sun.proxy.$Proxy8]
网上查询得知:
使用了jdk的自动动态代理,需要在<aop:aspectj-autoproxy中添加proxy-target-class="true"
<aop:config>
<!-- 定义程序的切入点 -->
<aop:pointcut expression="execution(* com.Spring..*.*(..)))" id="pointcut"/>
<!-- 这里ref的对象是通过annotation配置@Component出来的, -->
<!-- 定义面向方面的处理类 -->
<aop:aspect ref="serviceAspect">
<aop:before method="serviceBefore" pointcut-ref="pointcut"/>
<aop:after method="serviceAfter" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>
<aop:aspectj-autoproxy proxy-target-class="true"/>
执行后结果:

此时的业务层里面还没有出现任何的与业务层的核心操作有关的代码。而所有的辅助功能都会以切面的形式出现在项目的执行过程之中,而
这些切面就是最早的代理类。
步骤:
1,首先需要定义一个切面aop:pointcut ,里面包含这个切面所覆盖的位置,由表达式expression决定,然后还需要一个id值。
2,然后定义一个面向方面的处理类;aop:aspect,里面需要指定这个类的实例是哪个,上面用ref和annotation配置组合确定了。
3,分别指定由aop:aspect指定的处理类的aop:before,aop,after等方法,里面需要指定这个方法关联哪个切面,通过pointcut-ref指定切面,然后就会对该切面所
覆盖指定的类的对象,进行切面处理了,比如每次相关类实例对象调用方法的时候,aop:befer等方法也会被调用。
分析结果:
这里切面和我们的Service类关联起来的地方就是定义切面处的 expression="execution(* com.Spring..*.*(..)))" 。
只要符合这个表达式的类,这里就是这个包下面的类,的对象实例执行,在执行前和执行后都会调用切面类里面的方法,具体调用哪个方法
,有aop:before,或者aop:xxx 绝对。

整个配置过程中,其基本的操作意义基本一看明白,但是最重要的是切入点的设置。
execution(* com.Spring..*.*(..)))
这种语法就是AspectJ定义的切入点操作语法。此语法结构如下:
excution(修饰符匹配? 返回值类型 操作类型的匹配? 名称匹配(参数匹配) 抛出异常匹配) 这里的?表示一个或0个。
以上语法详细解释如下:
1,修饰符:public private ,只能出现0次或1次,(本次没有出现,默认public)
2,返回值:execution(* com.Spring..*.*(..)))。如果使用的是*,表示返回任意类型。
3,名称匹配:execution(* com.Spring..*.*(..))),表示的是具体要使用的此切面的程序类,如果写的是com.Spring表示这个包中的,
而如果出现“..”,则表示在任意子包下,随后的*.*表示任意类的任意方法,第一个*表示类名称,第二个表示方法名称。
4,方法参数:execution(* com.Spring..*.*(..))),使用“..”表示使用任意多个参数,如果使用的是“*”,表示匹配任意一个参数。
比如execution(* com.Spring..*.*(..)))就表示:在com.spring这个包下,任意返回值的任意类的,任意方法中,任意参数的地方,都要执行这个切面的拦截。
一旦拦截成功,就触发相应的处理方法,让我们的切面执行。
17-spring学习-AOP初步实现的更多相关文章
- [原创]java WEB学习笔记107:Spring学习---AOP切面的优先级,重用切点表达式
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- [原创]java WEB学习笔记106:Spring学习---AOP的通知 :前置通知,后置通知,返回通知,异常通知,环绕通知
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- [原创]java WEB学习笔记105:Spring学习---AOP介绍,相关概念,使用AOP,利用 方法签名 编写 AspectJ 切入点表达式
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- [原创]java WEB学习笔记104:Spring学习---AOP 前奏,通过一个问题引入动态代理
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- spring 学习 AOP和IOC
自11开始接触三大框架,至今已俞5载, 当时风光无限的ssh,现在还在被广泛使用,并有扩大之势的只有spring了 spring主要特性,是广为使用的AOP(面向切面)和IOC(控制反转) 1.其中, ...
- Spring学习-- AOP入门动态代理
AOP 的拦截功能是由 java 中的动态代理来实现的.说白了,就是在目标类的基础上增加切面逻辑,生成增强的目标类(该切面逻辑或者在目标类函数执行之前,或者目标类函数执行之后,或者在目标类函数抛出异常 ...
- 黑马Spring学习 AOP XML和注解配置 5种通知 切点切面通知织入
业务类 package cn.itcast.aop; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoin ...
- Spring学习(二)——Spring中的AOP的初步理解[转]
[前面的话] Spring对我太重要了,做个关于web相关的项目都要使用Spring,每次去看Spring相关的知识,总是感觉一知半解,没有很好的系统去学习一下,现在抽点时间学习一下Spring. ...
- Spring学习(二)——Spring中的AOP的初步理解
[前面的话] Spring对我太重要了,做个关于web相关的项目都要使用Spring,每次去看Spring相关的知识,总是感觉一知半解,没有很好的系统去学习一下,现在抽点时间学习一下Spring.不知 ...
随机推荐
- php上传中文文件文件名乱码问题
php上传文件是最最基础的一个技术点,但是深入进去也有不少问题需要解决,这不,上传中文文件后,文件名变成了乱码. 下面是问题代码,很简单: 1.问题代码 html部分: <html> &l ...
- GB2312简体中文编码表
GB2312简体中文编码表 code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F A1A0 . . · ˉ ˇ ¨ " 々 — - | … ...
- svn使用经验---不断总结
删除文件或文件夹 svn rm 名字 --force svn ci (系统会提示输入提交日志) 执行完这两步后,才能被真正删除 添加文件或文件夹 svn add 文件名 --force ...
- Java:volatile 关键字的一点理解
背景 学了六年C#,一直没有使用过 volatile,对多线程编程也是偶尔才会使用,这次学习 Java 又遇到了 volatile,准备稍微深入的了解一下. volatile 的作用? 几乎所有支持这 ...
- L脚本语言语法手冊 0.10版
L脚本语言语法手冊 0.10版 简 介 L脚本语言是一个轻量级的,旨在接近自然语言的编程语言,眼下支持在中文.英文基础上的编程.并可扩展为随意语种.L脚本语言的语法结构简单.程序结构相对 ...
- [Lua]mac 上安装lua
mac 安装lua google了好个看起来都不怎么好操作.这个是在命令行下操作的非常easy. curl -R -O http://www.lua.org/ftp/lua-5.2.3.tar.gz ...
- java jdk查看源代码
事实上假设你安装了JDK的话,你就已经拥有了java api的源代码. 安装JDK文件夹下的src.zip文件就是java api的源代码. 比方:C:\Program Files\Java\jdk1 ...
- Redis事务为什么不支持回滚
在事务运行期间,虽然Redis命令可能会执行失败,但是Redis仍然会执行事务中余下的其他命令,而不会执行回滚操作,你可能会觉得这种行为很奇怪.然而,这种行为也有其合理之处:只有当被调用的Redis命 ...
- Flask 学习(一)概述及安装
Flask 概述及安装 Flask 简介 Flask是一个使用 Python 编写的轻量级 Web 应用框架.其 WSGI 工具箱采用 Werkzeug ,模板引擎则使用 Jinja2 . 官方网址 ...
- TYVJ 2002 扑克牌 题解
P2002 扑克牌 时间: 1000ms / 空间: 131072KiB / Java类名: Main 背景 Admin生日那天,Rainbow来找Admin玩扑克牌……玩着玩着Rainbow觉得太没 ...