spring(二) AOP注入
AOP概念
l AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码
l 经典应用:事务管理、性能监视、安全检查、缓存 、日志等
l Spring AOP使用纯Java实现,不需要专门的编译过程和类加载器,在运行期通过代理方式向目标类织入增强代码
l AspectJ是一个基于Java语言的AOP框架,Spring2.0开始,Spring AOP引入对Aspect的支持,AspectJ扩展了Java语言,提供了一个专门的编译器,在编译时提供横向代码的织入
Aop的实现原理
l aop底层将采用代理机制进行实现。
专业术语
1.target:目标类,需要被代理的类。例如:UserService
2.Joinpoint(连接点):所谓连接点是指那些可能被拦截到的方法。例如:所有的方法
3.PointCut 切入点:已经被增强的连接点。例如:addUser()
4.advice 通知/增强,增强代码。例如:after、before
5. Weaving(织入):是指把增强advice应用到目标对象target来创建新的代理对象proxy的过程.
6.proxy 代理类
7. Aspect(切面): 是切入点pointcut和通知advice的结合
一个线是一个特殊的面。
一个切入点和一个通知,组成成一个特殊的面。
1.execution() 用于描述方法 【掌握】
语法:execution(修饰符 返回值 包.类.方法名(参数) throws异常)
修饰符,一般省略
public 公共方法
* 任意
返回值,不能省略
void 返回没有值
String 返回值字符串
* 任意
包,[省略]
com.itheima.crm 固定包
com.itheima.crm.*.service crm包下面子包任意 (例如:com.itheima.crm.staff.service)
com.itheima.crm.. crm包下面的所有子包(含自己)
com.itheima.crm.*.service.. crm包下面任意子包,固定目录service,service目录任意包
类,[省略]
UserServiceImpl 指定类
*Impl 以Impl结尾
User* 以User开头
* 任意
方法名,不能省略
addUser 固定方法
add* 以add开头
*Do 以Do结尾
* 任意
(参数)
() 无参
(int) 一个整型
(int ,int) 两个
(..) 参数任意
throws ,可省略,一般不写。
2.within:匹配包或子包中的方法(了解)
within(com.itheima.aop..*)
3.this:匹配实现接口的代理对象中的方法(了解)
this(com.itheima.aop.user.UserDAO)
4.target:匹配实现接口的目标对象中的方法(了解)
target(com.itheima.aop.user.UserDAO)
5.args:匹配参数格式符合标准的方法(了解)
args(int,int)
6.bean(id) 对指定的bean所有的方法(了解)
bean('userServiceId')
=======================================================================================
实例 :AOP基于xml配置开发
UserAOP.xml
<?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.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd"> <bean id="aspectUser" class="com.spring_aop1.AspectUser"></bean>
<bean id="user" class="com.spring_aop1.User"></bean> <aop:config>
<!-- expression="execution(返回值 包名.类名.方法名(参数类型)) id="任意":切入点名 -->
<aop:pointcut expression="execution(* com.spring_aop1.*.*(..))" id="myPointcut"/> <aop:aspect ref="aspectUser">
<aop:before method="password" pointcut-ref="myPointcut"/>
<aop:after-returning method="after" pointcut-ref="myPointcut" returning="obj"/>
<!-- <aop:around method="around" pointcut-ref="myPointcut" /> -->
<aop:around method="aroundR" pointcut-ref="myPointcut" /> <aop:after-throwing method="throwable" pointcut-ref="myPointcut" throwing="e"/>
</aop:aspect> </aop:config> </beans>
User.java
package com.spring_aop1; public class User { private String str; public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
} public void insert(){
System.out.println("insert====ok");
}
public void delete(){
System.out.println("delete====ok");
}
public void update(){
System.out.println("update====ok");
}
public void selete(){
System.out.println("insert====ok");
} }
AspectUser.java
package com.spring_aop1; import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint; public class AspectUser { /**
* 定义一个前置通知
* */
public void password(){
System.out.println("前置通知:密码验证=====成功");
} /**
* 定义一个后置通知(可得方法返回值)
* @param jp execution(void com.spring_aop.User.save())
* @param obj
* */
public void after(JoinPoint jp,Object obj){
String name = jp.getSignature().getName(); System.out.println("后置通知:after获取一个返回值类型====切入点");
System.out.println("after返回值信息为:"+name);
} /**
* 定义一个环绕通知
* @param pjp execution(void com.spring_aop.User.save())
* */
public void around(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("环绕通知:around执行环绕通知前执行");
pjp.proceed();
System.out.println("环绕通知:around执行环绕通知后执行");
}
/**
* 定义一个环绕通知(可得方法返回值)
* @throws Throwable
* */
public Object aroundR(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("环绕通知:around执行环绕通知前执行");
Object obj = pjp.proceed();
System.out.println("环绕通知:around执行环绕通知后执行"); String s = pjp.getSignature().getName();
System.out.println("around返回值的类型:"+obj+" around返回方法名:"+s);
return obj;
} /**
* 定义一个异常通知(可得方法返回值)
* @throws Throwable
* */
public void throwable(JoinPoint jp,Throwable e){
System.out.println("到我这里来,说明 你发生了异常======");
} }
Test.java
package com.spring_aop1; import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class UserTest { public static void main(String[] args) { String str = "com/spring_aop1/UserAop.xml";
ApplicationContext context = new ClassPathXmlApplicationContext(str); User user = (User)context.getBean("user");
user.insert(); } }
实例 :AOP基于注解开发
UserAOP.xml
<?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"
xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 自动扫描 配置 扫描所有注解 :使用注解注入 -->
<context:component-scan base-package="com.spring_aop2"></context:component-scan> <!-- 添加AOP的注解扫描 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans>
User.java
package com.spring_aop2; import org.springframework.stereotype.Component; @Component(value="user")
public class User { private String str; public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
} public void insert(){
System.out.println("insert====ok");
}
public void delete(){
System.out.println("delete====ok");
}
public void update(){
System.out.println("update====ok");
int i = 1/0;
}
public void selete(){
System.out.println("insert====ok");
} }
AspectUser.java
package com.spring_aop2; import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component; @Component("aspectUser") //组件
@Aspect //声明这是一个切面类
public class AspectUser { /**
* <aop:pointcut
* expression="execution(* com.spring_aop2.*.*(..))"
* id="myPointcut" />
* */
@Pointcut("execution(* com.spring_aop2.*.*(..))")
private void myPoint(){} /**
* 定义一个前置通知
* */
@Before("execution(* com.spring_aop2.*.*(..))") //指向切入点的Id(私有方法的方法名)
public void password(){
System.out.println("前置通知:密码验证=====成功");
} /**
* 定义一个后置通知(可得方法返回值)
* @param jp execution(void com.spring_aop.User.save())
* @param obj
* */
@AfterReturning(value="myPoint()",returning="obj")
public void after(JoinPoint jp,Object obj){
String name = jp.getSignature().getName(); System.out.println("后置通知:获取一个返回值类型====切入点");
System.out.println("after返回值信息为:"+name);
} /**
* 定义一个环绕通知
* @param pjp execution(void com.spring_aop.User.save())
* */
@Around("execution(* com.spring_aop.*.*(..))")
public void around(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("环绕通知:around执行环绕通知前执行");
pjp.proceed();
System.out.println("环绕通知:around执行环绕通知后执行");
}
/**
* 定义一个环绕通知(可得方法返回值)
* @throws Throwable
* */
public Object aroundR(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("环绕通知:around执行环绕通知前执行");
Object obj = pjp.proceed();
System.out.println("环绕通知:around执行环绕通知后执行"); String s = pjp.getSignature().getName();
System.out.println("around返回值的类型:"+obj+" around返回方法名:"+s);
return obj;
} /**
* 定义一个异常通知(可得方法返回值)
* @throws Throwable
* */
@AfterThrowing(value="myPoint()",throwing="e")
public void throwable(JoinPoint jp,Throwable e){
System.out.println("到我这里来,说明 你发生了异常======");
} }
Test.java
package com.spring_aop2; import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class UserTest { public static void main(String[] args) { String str = "com/spring_aop2/UserAop.xml"; ApplicationContext context = new ClassPathXmlApplicationContext(str); User user = (User)context.getBean("user");
user.insert();
//user.update(); } }
spring(二) AOP注入的更多相关文章
- spring(二) AOP之AspectJ框架的使用
前面讲解了spring的特性之一,IOC(控制反转),因为有了IOC,所以我们都不需要自己new对象了,想要什么,spring就给什么.而今天要学习spring的第二个重点,AOP.一篇讲解不完,所以 ...
- Spring之AOP二
在Spring之AOP一中使用动态代理将日志打印功能注入到目标对象中,其实这就是AOP实现的原理,不过上面只是Java的实现方式.AOP不管什么语言它的几个主要概念还是有必要了解一下的. 一.AOP概 ...
- Spring(二)--IoC&AOP
IOC 一.IOC概述: 一般指控制反转(inversion of Control),把创建对象的权利交给框架,Ioc容器控制对象,是框架的重要特征,并非是面向对象编程的专用术语.它包括依赖注入(DI ...
- spring源码分析(二)Aop
创建日期:2016.08.19 修改日期:2016.08.20-2016.08.21 交流QQ:992591601 参考资料:<spring源码深度解析>.<spring技术内幕&g ...
- Spring学习笔记(二)Spring基础AOP、IOC
Spring AOP 1. 代理模式 1.1. 静态代理 程序中经常需要为某些动作或事件作下记录,以便在事后检测或作为排错的依据,先看一个简单的例子: import java.util.logging ...
- 框架应用:Spring framework (二) - AOP技术
基础概念 线程中的方法栈 java程序虚拟机启动时会载入程序码,虚拟机会为每一条正在运行的线程生成一个方法调用栈,线程以方法运行为执行单位. AOP概念以及目标 AOP是面向切面编程,其实就是在不修改 ...
- spring学习(二) ———— AOP之AspectJ框架的使用
前面讲解了spring的特性之一,IOC(控制反转),因为有了IOC,所以我们都不需要自己new对象了,想要什么,spring就给什么.而今天要学习spring的第二个重点,AOP.一篇讲解不完,所以 ...
- SpringBoot系列: 理解 Spring 的依赖注入(二)
==============================Spring 容器中 Bean 的名称==============================声明 bean 有两个方式, 一个是 @B ...
- Spring中AOP主要用来做什么。Spring注入bean的方式。什么是IOC,什么是依赖注入
Spring中主要用到的设计模式有工厂模式和代理模式. IOC:Inversion of Control控制反转,也叫依赖注入,通过 sessionfactory 去注入实例:IOC就是一个生产和管理 ...
- 09 Spring框架 AOP (二) 高级用法
上一篇文章我们主要讲了一点关于AOP编程,它的动态考虑程序的运行过程,和Spring中AOP的应用,前置通知,后置通知,环绕通知和异常通知,这些都是Spring中AOP最简单的用法,也是最常用的东西, ...
随机推荐
- 基于Apache服务在centos7上搭建文件列表
参考文献: https://www.cnblogs.com/snake553/p/8856729.html https://blog.csdn.net/yejinxiong001/article/de ...
- 浅谈java虚拟机|系列2|JVM运行时
今天我们继续谈谈JVM架构. 今天主要讲讲JVM运行时, 先来一个图: 上篇文章,我们知道,JVM运行时,简单来说就是把class文件翻译成操作系统相关的机器码(或汇编语言),然后通过调用操作系统函数 ...
- c++列举出本地打印机和网络打印机名称
主要使用EnumPrinters函数 该函数枚举可用的打印机,打印服务器,域或印刷服务供应商. 代码:(开箱即用) #include <Windows.h> #include <st ...
- Python之常用模块之小结
复习os模块常用的一些操作 import os # 1.切换路径============= d = os.getcwd() #获取当前的工作路径 os.chdir('D:\\')#目录的切换 prin ...
- ZROI 19.07.30 简单字符串/ll
写在前面:今天下午药丸--不会字符串,全程掉线/ll 给出字符串\(S\),\(q\)次询问,每次给出\(a,b,c,d\),询问\(S[a,b]\)的所有子串和\(S[c,d]\)最长公共前缀的最大 ...
- Python开发WebService--使用soaplib库
Python开发WebService--使用soaplib库 使用soaplib开发基于Python语言的WebService主要有以下四个步骤:一.准备环境 S1:下载插件Python.s ...
- java 各版本新特性
Java 5,6,7,8,9,10,11新特性吐血总结 lkd_whh关注赞赏支持 12018.04.01 14:09:15字数 1,948阅读 10,615 作者:拔剑少年 简书地址:https:/ ...
- JAVA笔记17-容器之一 图、Collection接口、Iterator接口(重要)
掌握1136: (1)1个图 (2)1个类:Collections (3)3个知识点:For(了解),Generic泛型,Auto-boxing/unboxing(自动打包/解包) (4)6个接口:C ...
- [LOJ 6704] 健身计划
问题描述 九条可怜是一个肥胖的女孩. 她最近长胖了,她想要通过健身达到减肥的目的,于是她决定每天做n次仰卧起坐以达到健身的目的. 她可以将这n次动作分为若干组完成,每一次完成ai次仰卧起坐,每做完一次 ...
- mysql 发现 navicat 可以远程连接,代码无法远程连接
navicat可以远程连接, root账号也可以用代码连接. 其他的用户无法远程连接. 原因: 1.先检查下 mysql数据库里面 的 servers 表是否存在. 2.更新或者创建用户之后 使用: ...