Spring2~~~

news/2024/9/17 7:11:44/ 标签: spring

注解配置Bean

Spring的 IOC 容器检查到注解就会生成对象,但这个注解的具体含义不会识别 

  配置自动扫描的包

    <!--配置容器要扫描的包1. component-scan 要对指定包下的类进行扫描, 并创建对象到容器2. base-package 指定要扫描的包3. 含义是当spring容器创建/初始化时,就会扫描com.hspedu.spring.component包下的所有的 有注解 @Controller / @Service / @Respository / @Component类将其实例化,生成对象,放入到ioc容器--><context:component-scan base-package="com.hspedu.spring.component"/>

Map里的默认id是类名开头小写
com.hspedu.spring.component会扫描comonent及其子包
如果要扫描spring下的包,写成com.hspedu.spring.* 

只扫描包下的哪些类

在xml中加上 resource-pattern="User*.class" 表示只扫描spring.component 和它的子包下的User打头的类,用的比较少

<context:component-scan base-package="com.hspedu.spring.component" 
resource-pattern="User*.class" />

排除包下某种类型的注解(注解方式)

    <!--需求:如果我们希望排除某个包/子包下的某种类型的注解,可以通过exclude-filter来指定1. context:exclude-filter 指定要排除哪些类2. type 指定排除方式 annotation表示按照注解来排除3. expression="org.springframework.stereotype.Service" 指定要排除的注解的全路径--><context:component-scan base-package="com.hspedu.spring.component"><context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/><context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/></context:component-scan>

指定自动扫描哪些注解类(注解方式)

    <!--需求:如果我们希望按照自己的规则,来扫描包/子包下的某些注解, 可以通过 include-filter1. use-default-filters="false" 表示不使用默认的过滤机制/扫描机制2. context:include-filter 表示要去扫描哪些类3. type="annotation" 按照注解方式来扫描/过滤4. expression="org.springframework.stereotype.Service" 指定要扫描的注解的全路径--><context:component-scan base-package="com.hspedu.spring.component" use-default-filters="false"><context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/><context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/><context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/></context:component-scan>


使用 value 指定 id 值

        覆盖默认的id值
        注解默认 类名首字母小写 作为id值

@Service(value = "sss")
public class Student {
}

自动装配

@AutoWired

IOC容器中有多个对象,要进行查找
1、是否有唯一bean
2、根据id查找

根据id查找没找到,报错原因:按id找不到,按类型有多个,类型匹配不上

根据唯一性查找,属性名无所谓,直接按照类型找到
IOC容器中的对象和装配的对象哈希值不一定一样

    <!--自动扫描的id就是类名首字母小写或者指定value的id值--><context:component-scanbase-package="com.hspedu.spring.component"/><!--配置两个UserService对象--><bean class="com.hspedu.spring.component.UserService" id="userService200"/><bean class="com.hspedu.spring.component.UserService" id="userService300"/>
@Controller
public class UserAction {@Autowiredprivate UserService userService200;public void sayOk() {System.out.println("userAction 装配的 userService属性=" + userService);userService200.hi();}
}

@Qualifier与@AutoWired

必须搭配使用,相当于@Resource

@Resource

 按照name的值在容器中查找,属性名没有作用了

按照type类型查找,属性名没有作用了,要求在容器里只能有一个这样类型的对象 

  

如果没有指定name和type,则先试用byName注入策略,如果匹配不上,再使用byType策略

泛型依赖装配

        使用Autowired
        把PhoneDao对象装配到PhoneService,
通过泛型传入BaseDao,再把指定的泛型对象装配到PhoneService

动态代理 

不改变原有代码的情况下进行对象功能增强,使用代理对象拓展功能

public interface Vehicle {public void run();public String fly(int height);
}
public class Car implements Vehicle{@Overridepublic void run() {//System.out.println("交通工具开始运行了....");System.out.println("小汽车在路上 running....");//System.out.println("交通工具停止运行了....");}@Overridepublic String fly(int height) {System.out.println("小汽车可以飞翔 高度=" + height);return "小汽车可以飞翔 高度=" + height;}
}

 类似切面类

public class VehicleProxyProvider {//target_vehicle 表示真正要执行的对象//该对象的类实现了Vehicle接口private Vehicle target_vehicle;public VehicleProxyProvider(Vehicle target_vehicle) {this.target_vehicle = target_vehicle;}//编写一个方法,可以返回一个代理对象, 该代理对象可以通过反射机制调用到被代理对象的方法public Vehicle getProxy() {ClassLoader classLoader =target_vehicle.getClass().getClassLoader();//得到对象的接口信息Class<?>[] interfaces = target_vehicle.getClass().getInterfaces();//创建InvocationHandler 对象//因为 InvocationHandler 是接口,所以我们可以通过匿名对象的方式来创建该对象/**** public interface InvocationHandler {*  public Object invoke(Object proxy, Method method, Object[] args)*         throws Throwable;* }* invoke 方法是将来执行我们的target_vehicle的方法时,会调用到**/InvocationHandler invocationHandler = new InvocationHandler() {/*** invoke 方法是将来执行我们的target_vehicle的方法时,会调用到* @param o 表示代理对象* @param method 就是通过代理对象调用方法时,的哪个方法 代理对象.run()* @param args : 表示调用 代理对象.run(xx) 传入的参数* @return 表示 代理对象.run(xx) 执行后的结果.* @throws Throwable*/@Overridepublic Object invoke(Object o, Method method, Object[] args)throws Throwable {System.out.println("交通工具开始运行了....");//method 是?: public abstract void com.hspedu.spring.proxy2.Vehicle.run()//target_vehicle 是? Ship对象//args 是null//这里通过反射+动态绑定机制,就会执行到被代理对象的方法Object result = method.invoke(target_vehicle, args);System.out.println("交通工具停止运行了....");return result;}};/*public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)1. Proxy.newProxyInstance() 可以返回一个代理对象2. ClassLoader loader: 类的加载器.3. Class<?>[] interfaces 就是将来要代理的对象的接口信息4. InvocationHandler h 调用处理器/对象 有一个非常重要的方法invoke*/Vehicle proxy =(Vehicle)Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);return proxy;}
}

Test类 

    @Testpublic void proxyRun() {//创建VehicleProxyProvider对象, 并且我们传入的要代理的对象VehicleProxyProvider vehicleProxyProvider =new VehicleProxyProvider(new Car());//获取代理对象, 该对象可以代理执行方法//proxy的编译类型是 Vehicle, 运行类型是 class com.sun.proxy.$Proxy9Vehicle proxy = vehicleProxyProvider.getProxy();//当执行run方法时,会执行到 代理对象的invokeproxy.run();String result = proxy.fly(10000);System.out.println("result=" + result);}

getProxy()的缺点

硬编码,功能不强,希望以方法的形式来执行一段业务

写成方法,耦合度高

    //在目标对象执行前执行public void before(Method method, Object[] args) {System.out.println("before-方法执行前-日志-方法名-" + method.getName() + "-参数 "+ Arrays.asList(args)); //这里从AOP看,就是一个横切关注点-前置通知}//在目标对象执行后执行public void after(Method method, Object result) {System.out.println("after-方法执行正常结束-日志-方法名-" + method.getName() + "-结果result= "+ result);//从AOP看, 也是一个横切关注点-返回通知}

进行解耦,写成AOP类,复用性差,不灵活,硬编码

public class HspAOP {public static void before(Method method, Object[] args) {}public static void after(Method method, Object result) {}
}

AOP

面向切面编程

快速入门

 

环绕通知可以将四个通知合并管理

public interface SmartAnimalable {//求和float getSum(float i, float j);//求差float getSub(float i, float j);
}
@Component //使用@Component 当spring容器启动时,将 SmartDog注入到容器
public class SmartDog implements SmartAnimalable {@Overridepublic float getSum(float i, float j) {float result = i + j;System.out.println("方法内部打印result = " + result);return result;}@Overridepublic float getSub(float i, float j) {float result = i - j;System.out.println("方法内部打印result = " + result);return result;}
}

切面类 

  • @Before(value = "") 表示前置通知        
    value = "execution(public float spring.aop.aspectj.SmartDog.getSum(float, float)       
    指定切入到哪个类的哪个方法  形式是: 访问修饰符 返回类型 全类名.方法名(形参列表)
  • showBeginLog方法可以理解成就是一个切入方法
  • JoinPoint joinPoint 在底层执行时,由AspectJ切面框架, 会给该切入方法传入 joinPoint对象,通过该方法,程序员可以获取到 相关信息
@Aspect //表示是一个切面类
@Component //会注入SmartAnimalAspect到容器
public class SmartAnimalAspect {@Before(value = "execution(public float spring.aspectj.SmartDog.getSum(float, float))")public void showBeginLog(JoinPoint joinPoint) {//通过连接点对象joinPoint 可以获取方法签名//invoke(Object proxy, Method method, Object[] args)整合到joinPointSignature signature = joinPoint.getSignature();System.out.println(signature.getName() + "-参数 "+ Arrays.asList(joinPoint.getArgs()));}
}

XML开启AOP功能

    <context:component-scanbase-package="com.hspedu.spring.aop.aspectj"/><!-- 开启基于注解的AOP功能 --><aop:aspectj-autoproxy/>

如果不开启,.getClass()不会得到代理对象,只会得到当前运行的对象(相当于new)

Test类

    @Testpublic void smartDogTestByProxy() {ApplicationContext ioc =new ClassPathXmlApplicationContext("beans08.xml");//需要通过接口类型来获取到注入的SmartDog对象-就是代理对象SmartAnimalable smartAnimalable =ioc.getBean(SmartAnimalable.class);//SmartAnimalable smartAnimalable =//        (SmartAnimalable)ioc.getBean("smartDog");smartAnimalable.getSum(10, 2);}

以前是new一个对象,获得这个类的的代理对象

动态代理返回的对象是个代理对象,强转成接口的形式返回

Animal proxy =

        (Animal)Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);

return proxy;
(xml中开启AOP)现在通过接口类型获取的对象就是这个类的代理对象

细节

按接口来获取,多个类实现了接口会报错
UsbInterface interface = ioc.getBean(UsbInterface.class);

interface是代理对象,获取Phone类的代理对象,getBean()就相当于之前的getPorxy()
UsbInterface interface = (UsbInterface)ioc.getBean(Phone.class);
UsbInterface interface = (UsbInterface)ioc.getBean("phone");

切入表达式

重用

    //定义一个切入点, 在后面使用时可以直接引用, 提高了复用性@Pointcut(value = "execution(public float spring.aspectj.SmartDog.getSum(float, float)))")public void myPointCut() {}@Before(value = "myPointCut()")public void showBeginLog(JoinPoint joinPoint) {}@AfterReturning(value = "myPointCut()", returning = "res")public void showSuccessEndLog(JoinPoint joinPoint, Object res) {}@AfterThrowing(value = "myPointCut()", throwing = "throwable")public void showExceptionLog(JoinPoint joinPoint, Throwable throwable) {}


 

两种动态代理

jdk的Proxy

面向接口,只能增强实现类中接口中存在的方法
得到的对象是JDK代理对象的实例

生成的代理对象只能转换成接口不能转换成被代理类

 

Spring的CGlib

面向父类,可以增强父类的所有方法
得到的对象是被代理对象的子类

JoinPoint常用方法

返回通知中获取结果

在@AfterReturning 增加属性 , 比如 returning = "res",同时在切入方法增加 Object res
注意: returning = "res" 和 Object res 的 res名字一致

 异常通知中获取异常

环绕通知 

@Aspect
@Component
public class SmartAnimalAspect {//演示环绕通知的使用-了解//1. @Around: 表示这是一个环绕通知[完成其它四个通知的功能]//2. value = "execution(public float com.hspedu.spring.aop.aspectj.SmartDog.getSum(float, float)) 切入点表达式//3. doAround 表示要切入的方法 - 调用结构 try-catch-finally@Around(value = "execution(public float com.hspedu.spring.aop.aspectj.SmartDog.getSum(float, float))")public Object doAround(ProceedingJoinPoint joinPoint) {Object result = null;String methodName = joinPoint.getSignature().getName();try {//1.相当于前置通知完成的事情Object[] args = joinPoint.getArgs();List<Object> argList = Arrays.asList(args);System.out.println("AOP环绕通知[-前置通知]" + methodName + "方法开始了--参数有:" + argList);//在环绕通知中一定要调用joinPoint.proceed()来执行目标方法result = joinPoint.proceed();//2.相当于返回通知完成的事情System.out.println("AOP环绕通知[-返回通知]" + methodName + "方法结束了--结果是:" + result);} catch (Throwable throwable) {//3.相当于异常通知完成的事情System.out.println("AOP环绕通知[-异常通知]" + methodName + "方法抛异常了--异常对象:" + throwable);} finally {//4.相当于最终通知完成的事情System.out.println("AOP环绕通知[-后置通知]" + methodName + "方法最终结束了...");}return result;}
}

切面优先级

如果同一个方法,有多个切面在同一个切入点切入,优先级如何控制

@order(value = n) 来控制,n 越小,优先级越高

前置通知通过@order来判断顺序

基于XML配置AOP 

public interface SmartAnimalable {float getSum(float i, float j);float getSub(float i, float j);
}
public class SmartDog implements SmartAnimalable {@Overridepublic float getSum(float i, float j) {return result;}@Overridepublic float getSub(float i, float j) {return result;}
}

切面类将注解全部去掉 

public class SmartAnimalAspect {public void showBeginLog(JoinPoint joinPoint) {}public void showSuccessEndLog(JoinPoint joinPoint, Object res) {}public void showExceptionLog(JoinPoint joinPoint, Throwable throwable) {}public void showFinallyEndLog(JoinPoint joinPoint) {}
}

测试类 

    @Testpublic void testAspectByXML() {ApplicationContext ioc = new ClassPathXmlApplicationContext("beans09.xml");SmartAnimalable smartAnimalable =ioc.getBean(SmartAnimalable.class);smartAnimalable.getSum(10, 2);}
<?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:context="http://www.springframework.org/schema/context"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/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"><!--使用XML配置,完成AOP编程--><!--配置一个切面类对象-bean--><bean class="com.hspedu.spring.aop.xml.SmartAnimalAspect" id="smartAnimalAspect"/><!--配置一个SmartDog对象-bean--><bean class="com.hspedu.spring.aop.xml.SmartDog" id="smartDog"/><!--配置切面类, 细节一定要引入 xmlns:aop--><aop:config><!--配置切入点--><aop:pointcut id="myPointCut" expression="execution(public float com.hspedu.spring.aop.xml.SmartDog.getSum(float, float)))"/><!--配置切面的前置,返回, 异常, 最终通知--><aop:aspect ref="smartAnimalAspect" order="10"><!--配置前置通知--><aop:before method="showBeginLog" pointcut-ref="myPointCut"/><!--返回通知--><aop:after-returning method="showSuccessEndLog" pointcut-ref="myPointCut" returning="res"/><!--异常通知--><aop:after-throwing method="showExceptionLog" pointcut-ref="myPointCut" throwing="throwable"/><!--最终通知--><aop:after method="showFinallyEndLog" pointcut-ref="myPointCut"/><!--配置环绕通知--><!--<aop:around method=""/>--></aop:aspect></aop:config>
</beans>


http://www.ppmy.cn/news/1522549.html

相关文章

在 Go 语言中使用模块

模块很重要,因为它们允许将相关的代码文件组织到同一个包中,并以一种提高简单性和可重复性的方式组织代码。 1. 开始使用模块 从代码的角度看,模块是 Go 包和文件以及名为 go.mod 的文件的集合。在接下来的步骤中,将学习如何创建模块,然后使用它。 2. 第一步:创建项目目…

MATLAB绘图基础5:MATLAB数据导入

参考书&#xff1a;《 M A T L A B {\rm MATLAB} MATLAB与学术图表绘制》(关东升)。 5.MATLAB数据导入 5.1 从CSV文件读取数据 C S V {\rm CSV} CSV文件是一种纯文本文件&#xff0c;文件中的数据以逗号为分隔符进行字段分隔&#xff0c;每一行数据代表一条记录&#xff0c;每…

力扣416-分割等和子集(Java详细题解)

题目链接&#xff1a;416. 分割等和子集 - 力扣&#xff08;LeetCode&#xff09; 前情提要&#xff1a; 因为本人最近都来刷dp类的题目所以该题就默认用dp方法来做。 最近刚学完01背包&#xff0c;所以现在的题解都是以01背包问题为基础再来写的。 如果大家不懂01背包的话…

人生苦短我用Python Excel文件基本操作

人生苦短我用Python Excel文件基本操作 前言文件基本操作的模块和类pathlib.Path 类os.stat_result 类time.struct_time 命名元组time 模块shutil 模块 示例查看属性拷贝文件重命名文件查找文件批量操作 测试 前言 本文主要介绍通过Python中的pathlib模块&#xff0c;完成Exce…

【Android面试八股文】你能说说FragmentPagerAdapter 和 FragmentStatePagerAdapter的区别吗?

文章目录 一、FragmentPagerAdapter1.1 工作方式1.2 生命周期1.3 优缺点1.4 适用场景1.5 示例二、FragmentStatePagerAdapter2.1 工作方式2.2 生命周期2.3 优缺点2.4 适用场景2.4 示例三、FragmentPagerAdapter和FragmentStatePagerAdapter关于instantiateItem()方法和destroyI…

【Java中的位运算和逻辑运算详解及其区别】

Java中的位运算和逻辑运算详解及其区别 在 Java 编程中&#xff0c;位运算和逻辑运算是常见的两种操作类型。位运算用于操作整数的二进制位&#xff0c;而逻辑运算则是处理布尔值 (boolean) 的运算。本文将详细讲解这两种运算及其主要区别&#xff0c;并给出相应示例。 应用场…

Docker入门学习-01

Docker 官方文档 1. Docker 基础知识 1.1 什么是 Docker&#xff1f; Docker 是一个开源的平台&#xff0c;用于开发、交付和运行应用程序。它使用容器技术&#xff0c;将应用程序及其依赖打包在一个轻量级的可移植容器中。 1.2 Docker 的主要组件 镜像&#xff08;Image&a…

Django form.save 方法的详细分析

在 Django 中&#xff0c;form.save() 方法是用于将表单中的数据保存到数据库的核心方法。它的功能和实现可以分为几个重要的部分&#xff0c;下面就是我对 form.save() 方法的详细分析&#xff1a; 1、问题背景 在 Django 中&#xff0c;我们经常会使用 Form 来处理用户提交的…

2024 年高教社杯全国大学生数学建模竞赛 C 题 农作物的种植策略(详细思路+matlab代码+python代码+论文范例)

持续更新中,2024年数学建模比赛思路代码论文都会发布到专栏内,只需订阅一次! 完整论文+代码+数据结果链接在文末! 一、第一问 问题描述:假定各种农作物未来的预期销售量、种植成本、亩产量和销售价格相对于 2023 年保持稳定,每季种植的农作物在当季销售。如果某种作物每…

mysql基础知识-锁机制

文章目录 锁类型1. 共享锁&#xff08;Shared Locks, S锁&#xff09;2. 排他锁&#xff08;Exclusive Locks, X锁&#xff09;3. 意向锁&#xff08;Intention Locks&#xff09;4. 记录锁&#xff08;Record Locks&#xff09;5. 间隙锁&#xff08;Gap Locks&#xff09;6. …

SpringBoot和Mybatis框架怎么防止SQL注入

在 Spring Boot 和 MyBatis 中&#xff0c;防止 SQL 注入的主要方法包括&#xff1a; 1.使用 MyBatis 的动态 SQL MyBatis 提供了安全构建 SQL 查询的方式&#xff0c;推荐使用动态 SQL 标签&#xff08;如 <if>、<choose>、<foreach> 等&#xff09;构建查…

安卓玩机工具-----通用安卓玩机工具 “搞机助手”界面预览 推荐

在网络中有很多很好玩的工具。方便安卓机型联机使用各种功能。系列博文将详细的演示有些工具的特点与使用方法 搞机助手 作者&#xff1a;流水断崖 目前开发功能有&#xff1a;Twrp recovery全自动刷机&#xff0c;免Root冻结、卸载预装软件&#xff0c;免Root激活&#xff…

Azure和Transformers的详细解释

Azure AI 是微软提供的人工智能 (AI) 解决方案的集合&#xff0c;旨在帮助开发人员、数据科学家和企业轻松构建和部署智能应用程序。以下是对 Azure AI 各个方面的详细解释&#xff1a; Azure AI 主要组件 Azure Cognitive Services&#xff08;认知服务&#xff09;&#xff…

音频-语言大模型原理

重磅推荐专栏: 《大模型AIGC》 《课程大纲》 《知识星球》 本专栏致力于探索和讨论当今最前沿的技术趋势和应用领域,包括但不限于ChatGPT和Stable Diffusion等。我们将深入研究大型模型的开发和应用,以及与之相关的人工智能生成内容(AIGC)技术。通过深入的技术解析和实践经…

【Dash】feffery_antd_componenet 中的 AntdSpace

一、feffery_antd_componenet 中的 AntdSpace feffery_antd_components&#xff08;简称fac&#xff09;中的AntdSpace组件是一个基于Ant Design的Dash第三方组件&#xff0c;它用于在水平或垂直方向上放置多个元素&#xff0c;并提供元素之间的间距。以下是AntdSpace组件的一…

鸿蒙开发中实现自定义弹窗 (CustomDialog)

效果图 #思路 创建带有 CustomDialog 修饰的组件 &#xff0c;并且在组件内部定义controller: CustomDialogController 实例化CustomDialogController&#xff0c;加载组件&#xff0c;open()-> 打开对话框 &#xff0c; close() -> 关闭对话框 #定义弹窗 (CustomDial…

Google Maps API申请和集成到React Native应用中的教程

Google Maps API申请和集成到React Native应用中的教程 访问Google Cloud Console 打开浏览器,访问 https://console.cloud.google.com/使用您的Google账号登录 选择或创建项目 在页面顶部的项目下拉菜单中,选择现有项目或创建新项目如果创建新项目,点击"新建项目",…

本地如何快速启动静态服务器

本地快速启动静态服务器 有许多第三方库可以帮助你快速启动一个静态服务器&#xff0c;甚至无需编写代码。通过命令行运行这些库后&#xff0c;它们会自动启动一个服务器并打开指定端口&#xff0c;展示当前目录下的文件内容&#xff1a; 电脑得提前安装NodeJS 1、http-serv…

yum源404导致Could not resolve host: mirrorlist.centos.org

yum源更换错误问题记录 网上查询到的部分源过旧&#xff0c;现在已经不存在404&#xff0c;可以将报错信息中的无法访问的地址在浏览器中尝试。如下http://mirrorlist.centos.org/?release7&archx86_64&repoos&infrastock这个地址就已经不在。 可以网上搜一下最新…

UI(五)常用布局总结

自适应布局 1.1、线性布局&#xff08;LinearLayout&#xff09; 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列&#xff0c;Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距&#xff0c;达到各子组件…