畅销的网站建设,哪个网站开发是按月付费的,浙江网站建设的要求,做软件下载网站有哪些SpringBoot下的Spring——DAY04——动态代理总结、AOP、自定义注解进行拦截、动态获取注解参数、通知方法#xff08;内含源代码#xff09;
源代码下载链接地址#xff1a;https://download.csdn.net/download/weixin_46411355/87549575 目录SpringBoot下的Spring——DAY0…SpringBoot下的Spring——DAY04——动态代理总结、AOP、自定义注解进行拦截、动态获取注解参数、通知方法内含源代码
源代码下载链接地址https://download.csdn.net/download/weixin_46411355/87549575 目录SpringBoot下的Spring——DAY04——动态代理总结、AOP、自定义注解进行拦截、动态获取注解参数、通知方法内含源代码源代码下载链接地址[https://download.csdn.net/download/weixin_46411355/87549575](https://download.csdn.net/download/weixin_46411355/87549575)1.动态代理总结1.1 JDK动态代理特点1.2 CGlib动态代理1.2.1 CGLib特点说明1.3 动态代理的作用2 Spring中的AOP2.1 AOP介绍2.2 AOP中专业术语(难点)2.3 AOP 入门案例2.3.1 创建一个SpringBoot的module2.3.1 导入jar包2.3.2 项目工程结构2.3.3 配置类2.3.4 Service层2.3.4.1 接口2.3.4.2 实现类2.3.5 切入点表达式2.3.6 定义切面类2.3.7 让AOP生效2.3.8 编辑测试类2.4 AOP形象化的比喻2.5 关于切入点表达式解析2.5.1 bean标签写法2.5.2 within表达式2.5.3 execution表达式2.6 按照自定义注解进行拦截2.6.1 自定义注解2.6.2 切入点表达式写法2.6.3 在service层实现类UserServiceImpl的addUser()方法上添加自定义的注解2.7 动态获取注解参数2.7.1 自定义注解2.7.2 使用注解2.8.3 需求2.8.4 编辑切面类2.8 通知方法2.8.1 关于通知方法解析2.8.2 前置通知案例2.8.3 后置通知案例2.8.3.1 添加接口方法1.编辑接口2.编辑实现类2.8.3.2 编辑AOP切面类SpringAOP2.8.3.3 编辑测试案例2.8.3.4 测试效果2.8.4 异常通知案例2.8.4.1 让service层实现类代码报错2.8.4.2 异常通知案例2.8.4.3 测试结果常用注解1.动态代理总结
1.1 JDK动态代理特点
类型名称: class com.sun.proxy.$Proxy9要求: 要求被代理者,必须是接口或者是实现类.JDK代理是java原生提供的API 无需导包.JDK动态代理在框架的源码中经常使用.代理类和被代理类继承相同的接口所以两者为兄弟关系
1.2 CGlib动态代理
1.2.1 CGLib特点说明
历史原因: JDK动态代理要求必须有接口,但是某些类它没有接口,则无法使用JDK代理生成代理对象. 所以为了填补知识的空缺,则引入cglib代理.
问题说明: cglib动态代理 要求有无接口都可以创建代理对象. 问题? 如何保证和被代理者相同 答案(特点): 要求cglib动态代理继承被代理者.代理对象是被代理者的子类.
代理类和被代理类目标类两者是父子关系代理对象是目标类的子类。
1.3 动态代理的作用
说明1: 一般我们将业务层中的耦合性高的代码,采用动态代理的方式进行解耦.使得程序更加具有扩展性. (业务逻辑的解耦) 说明2: Spring专门针对动态代理的规则.封装了一套API 起名 AOP
2 Spring中的AOP
2.1 AOP介绍
在软件业AOP为Aspect Oriented Programming的缩写意为面向切面编程通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续是软件开发中的一个热点也是Spring框架中的一个重要内容是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离从而使得业务逻辑各部分之间的耦合度降低提高程序的可重用性同时提高了开发的效率。
总结: Spring中的AOP 利用代理对象在不修改源代码的条件下,对方法进行扩展.
2.2 AOP中专业术语(难点)
1).连接点: 用户可以被扩展的方法 2).切入点: 用户实际扩展的方法 3).通知: 扩展方法的具体实现 4).切面: 将通知应用到切入点的过程
2.3 AOP 入门案例
2.3.1 创建一个SpringBoot的module 2.3.1 导入jar包
!--引入AOPjar包文件--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-aop/artifactId/dependency 2.3.2 项目工程结构 2.3.3 配置类
SpringConfig.java
package com.jt.config;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;ComponentScan(com.jt)
Configuration
public class SpringConfig {}2.3.4 Service层
2.3.4.1 接口
package com.jt.service;public interface UserService {void addUser();void deleteUser();
}2.3.4.2 实现类
package com.jt.service;import org.springframework.stereotype.Service;Service
public class UserServiceImpl implements UserService {Overridepublic void addUser() {System.out.println(完成用户新增);}Overridepublic void deleteUser() {System.out.println(完成用户删除操作);}
}
2.3.5 切入点表达式
切入点表达式
bean(“对象的Id”) 每次拦截,只拦截1个within(“包名.类名”)execution(返回值类型 包名.类名.方法名(参数列表))annotation(注解的路径)
2.3.6 定义切面类
package com.jt;import com.jt.config.SpringConfig;
import com.jt.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class TestSpring_AOP {public static void main(String[] args) {ApplicationContext applicationContext new AnnotationConfigApplicationContext(SpringConfig.class);UserService userService applicationContext.getBean(UserService.class);//如果是实现类对象则方法没有被扩展//如果是代理对象则方法被扩展 aop有效的System.out.println(userService.getClass());//class com.jt.service.UserServiceImpl$$EnhancerBySpringCGLIB$$baeada27userService.addUser();}
}
2.3.7 让AOP生效
说明: 编辑配置类,添加EnableAspectJAutoProxy,让AOP机制有效
package com.jt.config;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;ComponentScan(com.jt)
Configuration
EnableAspectJAutoProxy//让spring中的AOP生效
public class SpringConfig {}
2.3.8 编辑测试类
package com.jt;import com.jt.config.SpringConfig;
import com.jt.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class TestSpring_AOP {public static void main(String[] args) {ApplicationContext applicationContext new AnnotationConfigApplicationContext(SpringConfig.class);//理论值根据接口获取实现类对象 但是与切入点表达式匹配为了后续扩展方便为其创建代理对象UserService userService applicationContext.getBean(UserService.class);//如果是实现类对象则方法没有被扩展//如果是代理对象则方法被扩展 aop有效的是代理对象/*getClass()是Object中的方法不拦截*/System.out.println(userService.getClass());//class com.jt.service.UserServiceImpl$$EnhancerBySpringCGLIB$$baeada27userService.addUser();}
}
2.4 AOP形象化的比喻
说明: AOP是一种抽象的一种概念,看不见/摸不着.所以需要大家对概念有自己的认知.
2.5 关于切入点表达式解析
2.5.1 bean标签写法
Pointcut(“bean(userServiceImpl)”) 只匹配ID为userServiceImpl的对象
2.5.2 within表达式
Pointcut(“within(com.jt.service.*)”) 匹配xx.xx.service下的所有对象
2.5.3 execution表达式
Pointcut(execution(* com.jt.service..*.*(..)))
拦截返回值类型任意 xx.xx.service包下所有子孙包的所有类的任意方法
Pointcut(execution(* com.jt.service..*.add*(..)))
拦截返回值类型任意 xx.xx.service包下所有子孙包的所有类.以add开头的方法2.6 按照自定义注解进行拦截
2.6.1 自定义注解
package com.jt.anno;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;Target(ElementType.METHOD) //注解对方法有效
Retention(RetentionPolicy.RUNTIME) //运行期有效
public interface MyAnnotation {//注解起标记作用}
2.6.2 切入点表达式写法 Pointcut(annotation(com.jt.anno.MyAnnotation))public void pointCutMethod(){}2.6.3 在service层实现类UserServiceImpl的addUser()方法上添加自定义的注解 测试类运行
2.7 动态获取注解参数
2.7.1 自定义注解
package com.jt.anno;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;Target(ElementType.METHOD)
Retention(RetentionPolicy.RUNTIME)
public interface Find {int id() default 0;
}
2.7.2 使用注解
在service层的实现类UserServiceImp的addUser()方法上面添加自定义注解Find(id101)
2.8.3 需求
利用前置通知打印注解中的id值
2.8.4 编辑切面类
/*** 知识点* 如果切入点表达式只对当前通知有效则可以按照如下方式编辑* 要求动态的拦截Find注解并且要获取Find注解中的参数Id* 难点动态获取注解的对象* 代码解释* 1.annoattion(find) 拦截find变量名称对应类型的注解* 2.当匹配该注解后将注解对象当做参数传递给find* 优势可以一步到位获取注解的内容避免了反射的代码*/Before(annotation(find))public void before2(Find find){System.out.println(ID的值为find.id());}
2.8 通知方法
2.8.1 关于通知方法解析
1.前置通知 在目标方法执行之前执行. 2.后置通知 在目标方法执行之后执行. 3.异常通知 在目标方法执行之后抛出异常时执行. 4.最终通知 都要执行的通知 说明: 上述的四大通知一般用于记录程序的运行状态.只做记录. 5.环绕通知 在目标方法执行前后都要执行的通知
2.8.2 前置通知案例
切面类 SpringAOP.java /*** 定义通知方法* 1.前置通知 在目标方法执行之前执行* 2.后置通知 在目标方法执行之后执行* 3.异常通知 在目标方法执行之后抛出异常时执行* 4.最终通知 都要执行的通知* 5.环绕通知 在目标方法执行前后都要执行的通知**记录程序的状态* 1.目标对象的class/类路径 com.jt.xx.xxx.UserServiceImpl* 2.目标对象的方法名* 3.目标对象的方法的参数信息* 4.获取目标对象方法的返回值* 5.获取目标对象执行报错的异常信息*/Before(pointCutMethod())public void before(JoinPoint joinPoint){//1.获取目标对象的类型Class? targetClass joinPoint.getTarget().getClass();//2.获取目标对象的路径String path joinPoint.getSignature().getDeclaringTypeName();//3.获取目标对象的方法名称String methodName joinPoint.getSignature().getName();//4.获取方法的参数Object[] args joinPoint.getArgs();System.out.println(类型 targetClass);System.out.println(类的路径: path);System.out.println(方法名: methodName);System.out.println(参数: Arrays.toString(args));}运行结果
2.8.3 后置通知案例
2.8.3.1 添加接口方法
1.编辑接口 package com.jt.service;public interface UserService {void addUser();void deleteUser();int findCount();//查询总数
}
2.编辑实现类 package com.jt.service;import com.jt.anno.Find;
import com.jt.anno.MyAnnotation;
import org.springframework.stereotype.Service;Service
public class UserServiceImpl implements UserService {Find(id 101)MyAnnotation//标记作用Overridepublic void addUser() {System.out.println(完成用户新增);}Overridepublic void deleteUser() {System.out.println(完成用户删除操作);}/*** 测试获取返回值的* return*/MyAnnotationOverridepublic int findCount() {return 1000;}
}
2.8.3.2 编辑AOP切面类SpringAOP //注意事项如果多个参数joinPoint必须位于第一位AfterReturning(valuepointCutMethod(),returning result)public void afterReturn(JoinPoint joinPoint,Object result){//如果需要获取当前的方法信息则可以通过joinPoint获取
// System.out.println(我是后置通知);System.out.println(我是后置通知获取方法的返回值result);}2.8.3.3 编辑测试案例
package com.jt;import com.jt.config.SpringConfig;
import com.jt.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class TestSpring_AOP02 {public static void main(String[] args) {ApplicationContext applicationContext new AnnotationConfigApplicationContext(SpringConfig.class);//理论值根据接口获取实现类对象 但是与切入点表达式匹配为了后续扩展方便为其创建代理对象UserService userService applicationContext.getBean(UserService.class);//如果是实现类对象则方法没有被扩展//如果是代理对象则方法被扩展 aop有效的是代理对象/*getClass()是Object中的方法不拦截*/System.out.println(userService.getClass());//class com.sun.proxy.$Proxy19userService.addUser();userService.findCount();//测试代返回值的方法}
}
2.8.3.4 测试效果 2.8.4 异常通知案例
2.8.4.1 让service层实现类代码报错 2.8.4.2 异常通知案例
throwing:获取异常信息,之后进行传递 //后置通知与异常通知是互斥的只能有一个AfterThrowing(value pointCutMethod(),throwing exception)public void afterThrow(JoinPoint joinPoint,Exception exception){//打印异常//exception.printStackTrace();System.out.println(我是异常通知exception.getMessage());}2.8.4.3 测试结果 常用注解
Configuration 标识当前类是配置类 ComponentScan 包扫描注解 扫描注解 Bean 标识该方法的返回值交给Spring容器管理 Scope 控制多例和单例 Lazy 懒加载 PostConstruct 初始化方法 PreDestroy 销毁方法 Component 将当前类未来的对象交给容器管理 Autowired 按照类型进行注入 Qualifier 按照名称进行注入 Repository 标识持久层注解 Service 标识Service层 Controller 标识Controller层 Value 为属性赋值 Value(“${key}”) PropertySource 加载指定路径的配置文件properties Aspect 标识当前类是一个切面类 Pointcut 用于定义切入点表达式 表达式写法4种 EnableAspectJAutoProxy 让AOP的注解有效果 Before AOP-前置通知 AfterReturning AOP-后置通知 AfterThrowing AOP-异常通知 After AOP-最终通知 Around AOP-环绕通知