spring-3-AOP
@Retention
(RetentionPolicy.RUNTIME),编译是保留运行时注解
package anno; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; //此注解依次可以在类 属性 方法进行
@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD}) //运行时可以查看注解信息
@Retention(RetentionPolicy.RUNTIME)
public @interface Entity {
//注解的参数
public String value();
}
2、定义dao(模拟映射)
package dao; import anno.Entity; @Entity("entity")
public class CityEntity {
private String id;
private String name; public void setId(String id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getId() {
return id;
}
}
package util; import anno.Entity;
import dao.CityEntity; public class UtilSql {
public static String builSqlStr(Object object){ Class clazz = object.getClass( ); // 先判断是否存在注解
if(clazz.isAnnotationPresent(Entity.class)){ //判断是否是自定义Entity注解
Entity entity = (Entity) clazz.getAnnotation(Entity.class); //获取相关注解传的值
String tableName = entity.value();
CityEntity cityEntity = (CityEntity) object;
String sql = "select * from "+tableName+" where id ='"+cityEntity.getId()+"' and name = '"+cityEntity.getName()+"'";
return sql;
}
return "没有获取到相关sql";
}
}
4、测试
package test; import dao.CityEntity;
import util.UtilSql; public class Test {
public static void main(String args[]){
CityEntity cityEntity = new CityEntity();
cityEntity.setId("1");
cityEntity.setName("wjw");
String sql = UtilSql.builSqlStr(cityEntity);
System.out.println(sql);
}
}
5、测试结果
6、先关项目截图
与OOP对比,AOP是处理一些横切性问题,这些横切性问题不会影响到主逻辑实现的,但是会散落到代码的各个部分,难以维护。AOP就是把这些问题和主业务逻辑分开,达到与主业务逻辑解耦的目的。
aop应用场景
1、日志记录
2、权限校验
3、效率检查
4、事务管理
5、.......
Aspect:切面,跨越多个类别的关注点的模块化。事务管理是企业Java应用程序中横切关注点的一个很好的例子。在Spring AOP中,方面是通过使用常规类(基于模式的方法)或使用注释的常规类来实现的
@Aspect
注释(@AspectJ样式)注释的。-
一定要给spring去管理 抽象 aspectj->类 xml->label
-
Join point:连接点,目标对象植入逻辑类中的的点(方法地方),目标对象就是代理对象的原对象。程序执行期间的一个点,例如执行方法或处理异常。在Spring AOP中,连接点始终表示方法执行。
Advice:建议,特定连接点的某个方面采取的操作。不同类型的建议包括“周围”,“之前”和“之后”建议。(建议类型将在后面讨论。)许多AOP框架(包括Spring)将建议建模为拦截器并在连接点周围维护一系列拦截器。
-
Before 连接点执行之前,但是无法阻止连接点的正常执行,除非该段执行抛出异常
After 连接点正常执行之后,执行过程中正常执行返回退出,非异常退出
After throwing 执行抛出异常的时候
After (finally) 无论连接点是正常退出还是异常退出,都会执行
Around advice: 围绕连接点执行,例如方法调用。这是最有用的切面方式。around通知可以在方法调用之前和之后执行自定义行为。它还负责选择是继续加入点还是通过返回自己的返回值或抛出异常来快速建议的方法执行。
-
Pointcut:切入点,就是连接点的集合,再主逻辑中的某一分支需要连接N(不定数)个方法,我们可以使用N个连接点或者直接使用切入点执行N个方法匹配连接点的谓词。建议与切入点表达式相关联,并在切入点匹配的任何连接点处运行(例如,执行具有特定名称的方法)。由切入点表达式匹配的连接点的概念是AOP的核心,Spring默认使用AspectJ切入点表达式语言。
Introduction:引入(简介),代表类型声明其他方法或字段。Spring AOP允许您向任何建议的对象引入新接口(以及相应的实现)。例如,您可以使用简介使bean实现
IsModified
接口,以简化缓存。(介绍被称为AspectJ社区中的类型间声明。)Target Object:目标对象,被代理对象的原对象。由一个或多个方面建议的对象。也称为“建议对象”。由于Spring AOP是使用运行时代理实现的,因此该对象始终是代理对象。
AOP proxy:AOP代理,由AOP框架创建的对象,用于实现方面契约(建议方法执行等)。在Spring Framework中,AOP代理是JDK动态代理或CGLIB代理。
Weaving:编织,将方面与其他应用程序类型或对象链接以创建建议对象。这可以在编译时(例如,使用AspectJ编译器),加载时间或在运行时完成。与其他纯Java AOP框架一样,Spring AOP在运行时执行编织
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?)
这里问号表示当前项可以有也可以没有,其中各项的语义如下
modifiers-pattern:方法的可见性,如public,protected;
ret-type-pattern:方法的返回值类型,如int,void等;
declaring-type-pattern:方法所在类的全路径名,如com.spring.Aspect;
name-pattern:方法名类型,如buisinessService();
param-pattern:方法的参数类型,如java.lang.String;
throws-pattern:方法抛出的异常类型,如java.lang.Exception;
example:
@Pointcut("execution(* com.chenss.dao.*.*(..))")//匹配com.chenss.dao包下的任意接口和类的任意方法
@Pointcut("execution(public * com.chenss.dao.*.*(..))")//匹配com.chenss.dao包下的任意接口和类的public方法
@Pointcut("execution(public * com.chenss.dao.*.*())")//匹配com.chenss.dao包下的任意接口和类的public 无方法参数的方法
@Pointcut("execution(* com.chenss.dao.*.*(java.lang.String, ..))")//匹配com.chenss.dao包下的任意接口和类的第一个参数为String类型的方法
@Pointcut("execution(* com.chenss.dao.*.*(java.lang.String))")//匹配com.chenss.dao包下的任意接口和类的只有一个参数,且参数为String类型的方法
@Pointcut("execution(* com.chenss.dao.*.*(java.lang.String))")//匹配com.chenss.dao包下的任意接口和类的只有一个参数,且参数为String类型的方法
@Pointcut("execution(public * *(..))")//匹配任意的public方法
@Pointcut("execution(* te*(..))")//匹配任意的以te开头的方法
@Pointcut("execution(* com.chenss.dao.IndexDao.*(..))")//匹配com.chenss.dao.IndexDao接口中任意的方法
@Pointcut("execution(* com.chenss.dao..*.*(..))")//匹配com.chenss.dao包及其子包中任意的方法
https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#aop-pointcuts-example 2、within
™表达式的最小粒度为类
// within与execution相比,粒度更大,仅能实现到包和接口、类级别。而execution可以精确到方法的返回值,参数个数、修饰符、参数类型等
@Pointcut("within(com.chenss.dao.*)")//匹配com.chenss.dao包中的任意方法
@Pointcut("within(com.chenss.dao..*)")//匹配com.chenss.dao包及其子包中的任意方法 3、args
args表达式的作用是匹配指定参数类型和指定参数数量的方法,与包名和类名无关
/**
* args同execution不同的地方在于:
* args匹配的是运行时传递给方法的参数类型
* execution(* *(java.io.Serializable))匹配的是方法在声明时指定的方法参数类型。
*/
@Pointcut("args(java.io.Serializable)")//匹配运行时传递的参数类型为指定类型的、且参数个数和顺序匹配
@Pointcut("@args(com.chenss.anno.Chenss)")//接受一个参数,并且传递的参数的运行时类型具有@Classifie
4、this JDK代理时,指向接口和代理类proxy,cglib代理时 指向接口和子类(不使用proxy)
5、target 指向接口和子类
/**
* 此处需要注意的是,如果配置设置proxyTargetClass=false,或默认为false,则是用JDK代理,否则使用的是CGLIB代理
* JDK代理的实现方式是基于接口实现,代理类继承Proxy,实现接口。
* 而CGLIB继承被代理的类来实现。
* 所以使用target会保证目标不变,关联对象不会受到这个设置的影响。
* 但是使用this对象时,会根据该选项的设置,判断是否能找到对象。
*/
@Pointcut("target(com.chenss.dao.IndexDaoImpl)")//目标对象,也就是被代理的对象。限制目标对象为com.chenss.dao.IndexDaoImpl类
@Pointcut("this(com.chenss.dao.IndexDaoImpl)")//当前对象,也就是代理对象,代理对象时通过代理目标对象的方式获取新的对象,与原值并非一个
@Pointcut("@target(com.chenss.anno.Chenss)")//具有@Chenss的目标对象中的任意方法
@Pointcut("@within(com.chenss.anno.Chenss)")//等同于@targ
proxy模式里面有两个重要的术语
proxy Class
target Class
CGLIB和JDK有区别 JDK是基于接口 cglib是基于继承所有this可以在cglib作用
根据官网写的简单切入点测试
1、javaConfig
package com.appconfig; import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy; //声明这是一个javaconfig
@Configuration
//扫描com包下的所有类
@ComponentScan("com")
//允许使用AdpectJ自动代理
@EnableAspectJAutoProxy //javaConfig
public class Appconfig {
}
2、模拟持久层用的查询
package com.dao;
import org.springframework.stereotype.Component; @Component
public class Wjw_Dao { public void query(){
System.out.println("我是query");
}
}
3、切入点类
package com.appconfig; import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component; //需要由容器管理
@Component //说明这是一个切面类
@Aspect
public class AspectjConfig { //连接点对哪些方法进行连接
@Pointcut("execution(* com.dao.*.*(..))")
public void pointcut(){ } //每次调用query之前需要处理的事情
@Before("pointcut()")
public void befor(){
System.out.println("我是切面再逻辑之前打印");
}
}
4、测试
import com.dao.Wjw_Dao;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class Test {
public static void main(String args[]){
AnnotationConfigApplicationContext acc = new AnnotationConfigApplicationContext(Appconfig.class);
Wjw_Dao wd = acc.getBean(Wjw_Dao.class);
wd.query();
}
}
5、截图
相关扩展点:自动代理(spring默认使用的是标准JDK中的proxy)
如果使用EnableAspectAutoProxy注解需要注意的是,当一个接口的实现类需要使用切入点或者连接点的时候需要设置默认参数为true
如果不设置则会出现找不到对应的代理对象类型(很奇怪的一个问题)
@EnableAspectAutoProxy(proxyTargetClass=true)
为什么要将默认参数设置为true?
因为此时生成的对象是proxy和Dao,唯独不是class对象,设置完后将使代理后的对象为目标对象
我们可以生成相关代理对象的字节码的文件进行查看。
public static void main (String args []){
Class<?>[] interfaces = new Class[]{Dao.class};
byte bytes [] = ProxyGenerator.generateProxyClass("wjwTest",interfaces);
File file = new File("D:\\test.class");
try{
FileOutputStream fw = new FileOutputStream(file);
fw.write(bytes);
fw.flush();
fw.close();
System.out.println("已完成");
}catch(IOException e){
System.out.println("exception");
e.getMessage();
}
扩展二,为什么javaJDK动态代理只能接口,而不能使用继承?
spring-3-AOP的更多相关文章
- Spring基于AOP的事务管理
Spring基于AOP的事务管理 事务 事务是一系列动作,这一系列动作综合在一起组成一个完整的工作单元,如果有任何一个动作执行失败,那么事务 ...
- Spring实现AOP的4种方式
了解AOP的相关术语:1.通知(Advice):通知定义了切面是什么以及何时使用.描述了切面要完成的工作和何时需要执行这个工作.2.连接点(Joinpoint):程序能够应用通知的一个“时机”,这些“ ...
- spring的AOP
最近公司项目中需要添加一个日志记录功能,就是可以清楚的看到谁在什么时间做了什么事情,因为项目已经运行很长时间,这个最初没有开来进来,所以就用spring的面向切面编程来实现这个功能.在做的时候对spr ...
- Spring(五)AOP简述
一.AOP简述 AOP全称是:aspect-oriented programming,它是面向切面编号的思想核心, AOP和OOP既面向对象的编程语言,不相冲突,它们是两个相辅相成的设计模式型 AOP ...
- Spring中AOP原理,源码学习笔记
一.AOP(面向切面编程):通过预编译和运行期动态代理的方式在不改变代码的情况下给程序动态的添加一些功能.利用AOP可以对应用程序的各个部分进行隔离,在Spring中AOP主要用来分离业务逻辑和系统级 ...
- Spring之AOP面向切片
一.理论基础: AOP(Aspectoriented programming)面向切片/服务的编程,在Spring中使用最多的是对事物的处理.而AOP这种思想在程序中很多地方可以使用的,比如说, ...
- 利用CGLib实现动态代理实现Spring的AOP
当我们用Proxy 实现Spring的AOP的时候, 我们的代理类必须实现了委托类的接口才能实现. 而如果代理类没有实现委托类的接口怎么办? 那么我们就可以通过CGLib来实现 package cn. ...
- spring之aop概念和配置
面向切面的一些概念: 简单说: 连接点就一些方法,在这些方法基础上需要额外的一些业务需求处理. 切入点就是方法所代表的功能点组合起来的功能需求. 通知就是那些额外的操作. 织入就是使用代理实现整个切入 ...
- Spring的AOP与代理
spring 支持两种注入方式: setter/constructor 支持多种配置方式: xml/java5注解/java类配置 支持两种事务管理: 声明性/编程性 实际上上述方式只有一个就能保证系 ...
- Spring 实践 -AOP
Spring 实践 标签: Java与设计模式 AOP引介 AOP(Aspect Oriented Programing)面向切面编程采用横向抽取机制,以取代传统的纵向继承体系的重复性代码(如性能监控 ...
随机推荐
- B - Preparing Olympiad
Time Limit:2000MS Memory Limit:262144KB 64bit IO Format:%I64d & %I64u Description You ha ...
- shell初级-----数据呈现方式
输入与输出 Linux系统将每个对象当作文件处理,这包括输入和输出进程.Linux用文件描述符来标识每个文件对象.文件描述符是一个非负整数,可以唯一标识会话中打开的文件.每个进程一次多可以有九个文件描 ...
- rbenv的使用
创建: 2017/09/05 更新: 2018/02/03 增加更新rbenv和获取list没有的版本 更新: 2018/02/25 把path里面[个人主机名]全部替换为[主机名] 更新: 2018 ...
- TP3.2单字母函数
A方法 A方法用于在内部实例化控制器 调用格式:A(‘[项目://][分组/]模块’,’控制器层名称’) 最简单的用法: $User = A('User'); 表示实例化当前项目的UserAction ...
- CH 6021 走廊泼水节
描述 [简化版题意]给定一棵N个节点的树,要求增加若干条边,把这棵树扩充为完全图,并满足图的唯一最小生成树仍然是这棵树.求增加的边的权值总和最小是多少. 我们一共有N个OIER打算参加这个泼水节,同时 ...
- LuoguP2700逐个击破【并查集/生成树/正难则反】By cellur925
题目传送门 题目大意:给你一棵树,求把其中k个点相互隔离(不连通)所需要的边权代价. 这题我开始是想要求出把k个点联通的最小代价的,但后来发现还是实现起来比较困难,题解里貌似也没有这种做法,于是就鸽了 ...
- (一)搭建自己的SpringBoot后台框架整合MyBatis
一:通过idea工具构建基础框架 1. 打开idea,左上角File→New→Project, 2. 点击Next 3. 点击Next,配置如下图,这里我们选择数据库MySQL和持久层框架MyB ...
- HTML5中div,article,section的区别
最近正在学习html5,刚接触html5,感觉有点不适应,因为有一些标签改变了,特别是div, section article这三个标签,查了一些资料,也试着用html5和css3布局网页,稍微有点头 ...
- SQL - nulls值排序问题
给字段排序时遇到的null值问题 当我们使用order by来为指定的字段进行排序时,如果db中该字段的值存在着null值,那么在排序时这些null值会不会参与排序呢?如果参与排序的话,又是以怎样的标 ...
- linux下使用svn创建版本库和权限管理
linux上的svn服务端如何和本地的电脑客户端结合使用 Linux上安装SVN服务器: 第一步:检查是否已安装 # rpm -qa subversion 第二步: 通过yum命令安装svnserve ...