当前位置: 首页 > news >正文

做网站编程序一级域名免费网站怎么申请

做网站编程序,一级域名免费网站怎么申请,安卓系统开发平台,百度网站收录提交目录 一、Spirng概括 1、什么是Spring 2、什么是容器 3、什么是IoC 4、模拟实现IoC 4.1、传统的对象创建开发 5、理解IoC容器 6、DI概括 二、创建Spring项目 1、创建spring项目 2、Bean对象 2.1、创建Bean对象 2.2、存储Bean对象#xff08;将Bean对象注册到容器…目录 一、Spirng概括 1、什么是Spring 2、什么是容器 3、什么是IoC 4、模拟实现IoC 4.1、传统的对象创建开发 5、理解IoC容器  6、DI概括 二、创建Spring项目 1、创建spring项目 2、Bean对象 2.1、创建Bean对象 2.2、存储Bean对象将Bean对象注册到容器中 2.3、获取Bean对象  【1】使用ApplicationContext接口获取 【2】使用BeanFactory获取Bean对象 【3】面试题ApplicationContext 和 BeanFactory的区别 3、注解 3.1、五大类注解之间的关系  3.2、使用类注解简易地存储Bean对象 3.2.1、配置扫描路径必备 3.2.2、通过注解注册Bean对象及直接获取 3.3、五大类注解Bean对象的命名规则 3.4、使用方法注解Bean 3.5、方法注解的Bean命名规则/Bean重命名  ※特殊情况方法注解Bean不能修饰有参的方法 3.6、简易地获取Bean对象对象装配/对象注入 1属性注入 2Setter注入 3构造方法注入 4Resource注解 3.7、多个同类型Bean对象的指定获取  三、Bean的作用域和生命周期 1、Bean作用域的理解 2、Bean的作用域 2.1、singleton作用域 2.2、prototype作用域 2.3、application作用域 2.4、request作用域 2.5、session作用域 2.6、websocket作用域 2.7、设置Bean对象作用域 3、Spring的执行流程 4、Bean的生命周期 一、Spirng概括 1、什么是Spring spring即spring Framework spring框架它作为一个开源的设计层面框架解决的是业务逻辑层和其他各层的松耦合问题因此它将面向接口的编程思想贯穿整个系统应用。 一句话概括spring是包含了众多工具方法轻量级的 IoC容器关键和面向切面AOP的开源容器框架 2、什么是容器 容器说到底就是用于容纳存储数据的一个基本装置。 像前面学的javeSE中的list/Map/泛型都是一个集合而集合是用于存储数据的也就是说集合是一个数据存储的容器。 以泛型为例Listlist这是一个只能存储和取出String类型数据的集合。 而Tomcat是Web容器.,存储Web项目和Servlet类的容器 3、什么是IoC IoCinversion of control控制权反转IoC是Spring中最核心的一个关键功能词。 控制反转也就是把控制权交给其他方 例如 本来程序是由一个A类来控制B类的生命周期在A类中要想使用B类就得new一个B类出来 但控制反转后就能把B类的生命周期交给其他人【如spring】控制此时使用B类就不用在 程序中实例化一个B类对象而是直接交由spring控制创建即可。 4、模拟实现IoC 4.1、传统的对象创建开发 此处创建一个手机对象程序为例创建一个逐级依赖的对象关系 手机Phone 依赖于 芯片 Chip 而芯片依赖于 电池 Battery 此处的程序想要运行Phone就得创建Chin因为彼此是依赖关系之后初始化Chin而Chin依赖于Battery就得在Chin类中创建一个Battery类从而才能调用使用Battery类。 ①手机类Phone public class Phone {private Chin chin;public Phone() {chin new Chin();}public void run() {System.out.println(Phone-init);chin.init();}public static void main(String []args){Phone phone new Phone();phone.run();} }②芯片类Chip public class Chin {private Battery battery;public Chin() {this.battery new Battery();}public void init(){System.out.println(Chin-init);battery.init();} } ③电池类Battery  public class Battery {//默认电池的容量private int capacity 100;public void init(){System.out.println(Battery-init; capacity:this.capacity);} } 对于上述传统的程序来说彼此类逐级依赖导致耦合度过高如果后续对该Phone类中的某个部件进行调整修改就会导致整个调用链上的类都要更改。 比如此处要修改Battery类中的capacity容量但是如果要从Phone类中直接传递参数逐级传参到Battery类就很麻烦。 代码如下  ①Phone类 public class Phone {private Chin chin;public Phone(int capacity) {chin new Chin(capacity);}public void run() {System.out.println(Phone-init);chin.init();}public static void main(String []args){Phone phone new Phone(200);phone.run();} } ②Chin类 public class Chin {private Battery battery;public Chin(int capacity) {this.battery new Battery(capacity);}public void init(){System.out.println(Chin-init);battery.init();} } ③Battery类 public class Battery {private int capacity 100;public Battery(int capacity) {this.capacity capacity;}public void init(){System.out.println(Battery-init; capacity:this.capacity);} } 上述的代码存在最致命的问题就是底层代码增加或修改需求时整个调用链上的所有代码都得发生改变。         而导致这种问题的原因是我们在每一个类的构造方法中处理下一层类的依赖关系都是自己手动new创建一个实例对象是主动创建的。         由自己创建的下级类当下级类发生修改时此处的创建实例操作也得进行修改。 要解决这个问题就可以采用控制权反转使用注入的方式将所需要的参数由本来的从上往下传递创建实例转为从下往上传递 原自己创建类当下级类发生改变时当前的类也要进行修改改为注入的方式后下级类发生改变当前类就不需要再进行代码修改了。 这就能完成代码的解耦降低耦合性耦合性也可以换⼀种叫法叫程序相关性。好的程序代码的耦合性代码之间的相关性是很低的也就是代码之间要实现解耦。 此处也可以理解成当客户要求产品进行参数修改时不再又我们自己调整而是外包出去交由第三方处理因此我们就无需出力照样按原来的流程进行传递即可。 控制权反转后的代码 ①NewPhone类 public class NewPhone {private NewChin newChin;public NewPhone(NewChin newChin) {this.newChin newChin;}public void run(){System.out.println(NewPhone_init);newChin.init();} } ②NewChin类 public class NewChin {private NewBattery newBattery;public NewChin(NewBattery newBattery) {this.newBattery newBattery;}public void init(){System.out.println(NewChin_init);newBattery.init();} } ③NewBattery类 public class NewBattery {private int capacity 100;public NewBattery(int capacity) {this.capacity capacity;}public void init(){System.out.println(NewBattery_init;capacity:capacity);} } ④启动类 由原来自己手动在类中创建下级类转为注入方式控制权反转把控制权转交其他类此处以App类为例处理再由该类调用传参。         此处可以很明显地观察到反转的特性由原来创建Phone类依次依赖往下控制创建Battery类【反转】转为 根据参数创建NewBattery类再往后依次注入到上级对象。         通⽤程序的实现代码类的创建顺序是反的传统代码是 Phone 控制并创建了ChinChin 创建并创建了 Battery依次往下⽽改进之后的控制权发⽣的反转不再是上级对象创建并控制下级对象了⽽是下级对象把注⼊将当前对象中下级的控制权不再由上级类控制了这样即使下级类发⽣任何改变当前类都是不受影响的这就是典型的控制反转也就是 IoC 的实现思想。 public class App {public static void main(String[] args) {int capacity 200;NewBattery battery new NewBattery(capacity);NewChin newChin new NewChin(battery);NewPhone newPhone new NewPhone(newChin);newPhone.run();} } 5、理解IoC容器  ✔Spring是集合众多工具方法的开源Ioc容器而IoC容器又为控制反转容器。 容器顾名思义就是用于存储数据和获取数据的一个东西。而作为Spring最核心的东西---IoC容器。 那么Spring最核心也是最基础的功能就是如何将对象存储到Spring且怎么从Spring中取出对象的过程。 将对象存储到Spring容器中当要使用的时候就从容器中获取即可Spring使用的是“懒汉模式”使用这种模式可以提高开发效率也可以减少 每次创建销毁对象带来带来的内存开销不然每次使用一个对象就new一个太过于浪费空间。 【懒汉模式会在第一次使用时才创建对象而在之前则不会创建从而避免了在系统启动或者初始化时就创建对象的过程。这种方式被称为“懒汉” 是因为它在初始化阶段并不匆忙而是等待真正需要时才会采取行动。】 优点实现代码的解耦、节省系统的资源提高了程序运行的效率 6、DI概括 DIDependency Injection依赖注入跟创建Servlet项目中引入依赖类似要使用什么样的功能就从Maven中央仓库获取jar包引入进去。 DI和IoC其实是在不同维度上的同一实现方法只是角度不同。所谓依赖注⼊就是由 IoC 容器在运⾏期间         动态地将某种依赖关系注⼊到对象之中。所以依赖注⼊DI和控制反转IoC是从不同的度的描述的同⼀件事情就是指通过引⼊IoC 容器利⽤依赖关系注⼊的⽅式实现对象之间的解耦。         说到底IoC是一种思想IoC 是“⽬标”也是⼀种思想⽽⽬标和思想只是⼀种指导原则最终还是要有可⾏的落地⽅案而DI是实现该思想的具体方法。要想实现IoC控制反转有很多的方法而DI只是其中一种。 二、创建Spring项目 1、创建spring项目 ①创建Maven项目 【注意】项目的存储路径不能有中文 ②添加Spring的框架依赖  添加完Spring的依赖后可以理解为该maven项目变为Spring Core项目 在项⽬的 pom.xml 中添加 Spring 框架的⽀持需要spring context【spring上下文也就是表示spring】及spring beans管理对象的模块可以从Maven中央仓库获取xml 配置如下 下述jar包版本号中的Release表示的是当前版本是稳定的当前更新停止可以用于发行的版本如果是snapshot 版本则代表不稳定、尚处于开发中的版本即快照版本 dependenciesdependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactIdversion5.2.3.RELEASE/version/dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-beans/artifactIdversion5.2.3.RELEASE/version/dependency /dependencies 引入spring框架依赖后左侧可以看到一些列jar包除了jdk1.8、spring-beans和spring-context外其他是配套出现的 ③添加一个启动类  最后在创建好的项⽬ java ⽂件夹下创建⼀个启动类包含 main ⽅法实现方法细节后续再补充即可 public class App {//创建启动类public static void main(String[] args) {} } 2、Bean对象 2.1、创建Bean对象 创建一个Bean对象跟普通java程序中创建的对象一样此处随便创建一个对象即可,要想增添方法、属性也可以. public class User {//创建一个Bean对象public void functino(){System.out.println(Start!);} } 2.2、存储Bean对象将Bean对象注册到容器中 此处的创建Bean对象存入Spring中此处的存储并不是真正执行存储的动作而是告诉spring此时要把某些类存储/托管给spring。 只是告诉spring要存储对象什么时候存储是与我们没关系我们只是使用方要使用该对象的时候再到spring取就行不关注什么时候存只在乎能不能拿到 ✔通过xml配置文件告诉spring要存储的Bean对象 【注意】在创建好的项目中添加配置文件需要将其放到resources根目录下新建一个自定义命名非中文的.xml文件再将下述配置代码写入即可 此处的Bean对象User类是存放在包里的因此在配置Bean时bean的class类名也必须要包含包名即完整路径名 下述的Spring 配置⽂件的固定格式(此处只是声明要把对象存储到Spring当中)为以下内容 ?xml version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdbean iduser_bean classcom.test.element.User/bean /beans 2.3、获取Bean对象  根据前面在spring配置文件中注册进Bean对象后要想获取该对象就得先拿到Spring对象才可以拿到里面存放的Bean对象。 【1】使用ApplicationContext接口获取 ApplicationContext是Spring中的一个接口通过该接口可以获取到Spring的上下文得到 Spring 的上下⽂对象创建的时候需要配置 Spring 配置信息.         它作为一个接口需要实现创建一个ClassPathXmlApplicationContext通过传入spring配置文件的命名去调用其构造方法创建出来。 ApplicationContext context new ClassPathXmlApplicationContext(配置文件名); 之后通过调用该Spring上下文对象中的getBean()即可获取Bean对象。 而该getBean方法还有三种不同的参数的传递: getBean(String) --- 传入在spring配置文件中注册入的Bean对象id该方法的返回类型是Object类需要进行强转 public class App1 {public static void main(String[] args) {//1.ApplicationContext context new ClassPathXmlApplicationContext(spring_config.xml);User user (User)context.getBean(user_bean);user.function();} }getBean(Class) --- 传入Bean对象的类型映射由于已经传入了Bean对象的类型自然无需像上一个进行类型强转getBean(String,Class) --- 同时传入Bean对象的id和类型 ①此处对于getBean(String)和getBean(Class) 还是有区别的当返回的Bean对象是null时第一个方法依然会对null进行类型强转而第二个方法无需强转。 ②当Spring当中出现两个类型一样id不一样的Bean对象时如果使用的是getBean(Class) 方法获取就会出现报错。通过此处的报错NoUniqueBeanDefinitionException可以知道没有唯一的一个Bean对象此处相同类型的Bean对象有两个无法同时获取两个Bean对象从而报错。【正确做法就是使用id去获取或者结合id和类型获取】 spring中的xml配置文件  //错误的获取Bean方法 public class App1 {public static void main(String[] args) {//1.ApplicationContext context new ClassPathXmlApplicationContext(spring_config.xml);User user context.getBean(User.class);User user1 context.getBean(User.class);user.function();user1.function();} } ③spring配置文件中对于Bean对象的注册其id标识不能重复使用不然在根据id标识获取Bean对象无法准确得知要获取具体哪一个Bean对象。此处的报错内容明显的可以知道命名为user_bean的id标识已经被使用过了正确做法指定不重复的id //错误代码 public class App1 {public static void main(String[] args) {ApplicationContext context new ClassPathXmlApplicationContext(spring_config.xml);User user context.getBean(User.class);user.function();} } 【2】使用BeanFactory获取Bean对象 public class App1 {public static void main(String[] args) {BeanFactory beanFactory new XmlBeanFactory(new ClassPathResource(spring_config.xml));User user beanFactory.getBean(User.class);user.function();} } 【3】面试题ApplicationContext 和 BeanFactory的区别 ApplicationContext和BeanFactory效果其实是一样的都是可以获取到Bean对象。 两者的区别在于 ApplicationContext是在初始化的时候就一次性加载获取spring中所有的Bean对象而BeanFactory是要获取的时候才获取懒汉执行速度比较快  相对轻量但是ApplicationContext一次性获取后就一劳永逸后续再想获取其他Bean对象效率都会很高。ApplicationContext接口是BeanFactory接口的子类java中的继承关系可知子类继承父类会具有父类所有的属性和方法而ApplicationContext作为子类又有自己独特的方法和属性所以相比于父类BeanFactory功能更多其还添加了对国际化⽀持、资源访问⽀持、以及事件传播等⽅⾯的⽀持。 3、注解 注解说到底就是一种功能声明. 通过多层类注解可以让后续对代码的管理和维护更方便 使其他人更能直观地了解当前类的用途 Spring中的注解可以分为1类注解2方法注解  ①类注解又可以分为 Controller控制器存储实现前后端交互的时候前端分发请求到后端的第一层入口【用途验证前端传递的参数安全检查】Service服务层经过安全检查才可以享受服务【此处为服务调用的编排和汇总】编排服务之间的优先级编排哪个先完成汇总请求发送到后端后服务层会实现两个接口的调用服务当中会把后端需要更新的两张表的所有接口都在这个方法实现这就是汇总Repository仓库存储---数据仓库、数据持久层直接操作数据库Component组件存储通用化的工具类Configuration配置存储存放项目中所有的配置比如拦截器、过滤器 Controller、Service、Repository是要满足用户请求的; 而Component组件是通用化的工具类例如定义了一个密码类用于加密和解密功能的该类就不用前面三大类注解因为其是和业务没有关系的而是使用Component组件注解 ②方法注解Bean也可以通过方法注解将当前方法返回的Bean对象存储到Spring中          3.1、五大类注解之间的关系  1Controller 2Service 3Repository 4Configuration  5Component  通过观察上述的五大类注解源码可以清楚地知道Controller、Repository、Configuration、Service四大注解都是依靠Component注解实现的说到底这四个注解是针对组件注解的扩充和扩展。  3.2、使用类注解简易地存储Bean对象 3.2.1、配置扫描路径必备 为了不让spring一次性进行全盘扫描耗时间、耗资源可以在spring配置文件中配置存储一下存储对象的扫描路径即可。 那么spring就只会在这个包名下扫描哪些类是有被注解修饰的才可以判断知道哪些是存放到spring中的Bean对象 下述配置了com.test.element这个包: ?xml version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contenthttp://www.springframework.org/schema/contextxsi:schemaLocationhttp://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.xsdcontent:component-scan base-packagecom.test.element/content:component-scan /beans 【注意】如果不设置扫描路径其不会扫描任何类。 3.2.2、通过注解注册Bean对象及直接获取 在想要注册进spirng的类前添加类注解即可 Controller public class User {public void function(){System.out.println(测试!);} } public class App {public static void main(String[] args) {//从spring容器中获取Bean对象//1. 通过ApplicationContext来获取Spring上下文////通过注解来将Bean对象注册到Spring中不像原方法直接手动在配置文件中注册没有指定Bean对象的Id标识//因此在获取Bean对象时就不清楚要根据什么去获取。而注解默认提供了Bean对象的Id标识为类型小驼峰如此处的“user”// 根据id和类名去找到对应根路径下的包名扫描是否有被注解修饰的类给注册到Spring中从而去获取对应的Bean对象ApplicationContext context new ClassPathXmlApplicationContext(spring_config.xml);User user context.getBean(user,User.class);user.function();//2.通过BeanFactory来获取Spring上下文BeanFactory beanFactory new XmlBeanFactory(new ClassPathResource(spring_config.xml));User user1 (User)beanFactory.getBean(user);user1.function();} } 3.3、五大类注解Bean对象的命名规则 默认情况下五大类注解的Bean名称是按类名首字母小写的规则来获取的。 创建一个Bean对象时其类名为大驼峰形式当要想获取Bean对象时传递的id参数字符串是其类名的首字母小写形式。如User - user Controller public class User {public void function(){System.out.println(测试!);} } public class App {public static void main(String[] args) {ApplicationContext context new ClassPathXmlApplicationContext(spring_config.xml);User user context.getBean(user,User.class);user.function();} } 特殊情况当创建的对象类名为前两个字母大写而不是大驼峰形式如IException 还是通过传入首字母小写的id标识去spring中获取Bean对象是找不到的 下述演示的注册IException对象就没办法通过首字母小写形式获取。 Controller public class IException {public void function(){System.out.println(成功);} } public class App2 {public static void main(String[] args) {ApplicationContext context new ClassPathXmlApplicationContext(spring_config.xml);IException iException context.getBean(iException,IException.class);iException.function();} } 1要想查清为什么spring根据该命名无法找到Bean对象就只能进到spring的源代码中了解Spring关于Bean存储时的命名规则。 在IDEA中连续按两次Shift键进入查询界面因为要想知道Spring的命名规则可以根据BeanName这一关键词去搜索。 2通过观察该类中的方法名找到这个符合我们需求的一个方法bulidDefaultBeanName创建默认Bean命名 3在该方法中最关键的就是最后的这个调用了jdk中Introspector类的decapitalize()【因此此处是spring调用jdk里面的命名规则】 该方法翻译过来是小写化的意思。此处将一个字符串即Bena对象名字符串传进去 4在该方法中最关键就是第二个if语句当Bean对象命名中的一个字母 和第二个字母都是大写时直接返回原命名字符串这就是为什么在getBean()从Spring中找Bean对象时根据其原命名规则首字母小写找不到对象。因为我们存入的Bean对象命名是前两个字母大写在Spring中获取时是以其原Bean对象命名去查询获取的。 【总结】注解Bean的名称要么是首字母小写要么是原类名 因此正确的做法就是在getBean时如果是前两个字母为大写就直接传入原对象类名即可. //正确做法 Controller class IException {public void function(){System.out.println(成功);} }public class App2 {public static void main(String[] args) {ApplicationContext context new ClassPathXmlApplicationContext(spring_config.xml);IException iException context.getBean(IException,IException.class);iException.function();} } 3.4、使用方法注解Bean 前面学习的类注解是只能应用到类上而此处的方法注解只能用到方法上。可以通过方法注解修饰的方法返回其类对象将该对象存储到Spring中。 用法在想要返回注册的Bean对象方法前面加上Bean注解 但有最关键的一点很容易出错错误代码如下 public class Test {Beanpublic User user(){//此处不是说在spring中还是用new创建对象的意思而是一种构建数据的方法User user new User();return user;} } public class App2 {public static void main(String[] args) {ApplicationContext context new ClassPathXmlApplicationContext(spring_config.xml);User user context.getBean(user,User.class);user.function();} } 从报错信息上看可以看出并没有找到名为user的Bean对象。         这是因为方法注解必须要配合类注解来使用此处的场景跟原获取Bean对象时Spring配置文件当中设置扫描路径差不多。         如果没有配合类注解的话就会对程序中所有的类进行扫描看哪些类中出现被Bean方法注解修饰的方法再去获取其对应返回的Bean对象效率太低。配合了类注解就会直接从加上类注解的类中去查找方法注解修饰的方法不会扫描到其他普通的方法大大提高了运行的效率。 3.5、方法注解的Bean命名规则/Bean重命名  对于方法注解默认通过方法名去找Bean对象的规则其实有一个很大的弊端。 因为可能出现不同包或同一包底下的类中出现具有相同方法名且返回同一类型对象的方法。这两个方法同时被Bean注解修饰就意味着在从spring中获取Bean对象不知道是获取哪一个。 但实际上次由Bean注解将方法的返回值对象注册到Spring中的方法如果出现一样方法名时第二个注册进spring的对象会覆盖前一个注册进去的对象这就会导致当我们想获取的Bean对象是第一个被覆盖的时候就无法获取到。 这种场景类似于 Map存入的key值有且只有一个相当于方法名往后继续存入同一key值就会覆盖上一个存入的key而value值就可以是重复的。 1User类 public class User {private int id;private String name;public int getId() {return id;}public void setId(int id) {this.id id;}public String getName() {return name;}public void setName(String name) {this.name name;} } 2UserService类  Controller public class UserService {Beanpublic User user(){User user new User();user.setName(测试一);return user;} } 3UserRepository类 Controller public class UserRepository {Beanpublic User user(){User user new User();user.setName(测试二);return user;} } 4启动类 public class App {public static void main(String[] args) {ApplicationContext context new ClassPathXmlApplicationContext(spring_config.xml);User user context.getBean(user,User.class);System.out.println(user.getName());} } 此处调用的结果是 “测试一”而不是“测试二”这里就验证了同方法名覆盖导致无法获取理想Bean对象的问题。  为了解决这种问题spring中有一规则可以针对Bean对象进行重命名使其可以针对特定命名的Bean对象进行存储或获取的处理。 重命名的方法有三种 在Bean注解后添加以name作为key值的参数修改。Bean(name )直接在Bean注解后添加重命名的字符串 Bean( )也可以使用花括号形式【Bean(name{test1,test2})】进行多组命名让一个Bean对象同时具有多个名字。【name也可以省略如Bean({test1,test2})】 当给这几个被Bean注解修饰的方法进行重命名后就可以通过指定新命名去获取Bean对象了。 比如 Controller public class UserRepository {Bean(name user2)//也可以是Bean(user2)public User user(){User user new User();user.setName(测试二);return user;} } public class App {public static void main(String[] args) {ApplicationContext context new ClassPathXmlApplicationContext(spring_config.xml);User user context.getBean(user2,User.class);System.out.println(user.getName());} } //调用输出的结果就为测试二 【注意】使用Bean注解重命名后就无法再用原首字母小写的命名规则获取或存储Bean对象了 ;(以上述为例已经重命名了Bean(user2)但还是使用方法名去spring找Bean对象就会找不到) public class App {public static void main(String[] args) {ApplicationContext context new ClassPathXmlApplicationContext(spring_config.xml);User user context.getBean(user,User.class);System.out.println(user.getName());} } ※特殊情况方法注解Bean不能修饰有参的方法 在同一类中出现多个方法重载返回类型一样参数列表不同的场景中如果要同时将这些方法返回的类对象注册到Spring中是无法做到的。         Bean方法注解只能修饰在无参的方法上如果是有参的方法Spring初始化存储时并不能给该方法提供一个参数因此就会出现该方法无法实现返回Bean对象给注册到Spring中。 3.6、简易地获取Bean对象对象装配/对象注入 Spring中获取Bean对象的方法称为“对象装配”也可以叫做“对象注入”即把对象从spring中取出来放到某个类属性中。 对象注入一共可以分为三种方法 属性注入Setter注入构造方法注入 1属性注入 属性注入直接在类中的成员变量前使用AutoWired 自动装配即可。 【注意】不能直接(在main方法中)使用属性注入后的变量这是由于spring的加载比较靠后 对于静态方法来说它是JVM启动的时候就加载可以使用的。 static方法执行的时间非常早比此处的属性注入还早这就导致main执行后属性注入还没有拿到spring中的Bean对象。此处主要是SpringCore项目才会出现这样的问题后续的Spring boot、SpringMVC项目就不会担心出现这种情况因为不需要main方法就可以直接启动springmain方法已经内置在spring容器里依靠内置容器启动所以就可以随心所欲的进行对象注入 正确的做法此处是将User对象注入到UserService之后在启动类中获取UserService对象就可以调用该类中的getUser()方法输出user因为UserService中已经通过属性注入获取spring中的user对象 ✔属性注入的缺点      1功能缺陷不能注入final修饰的属性final修饰的变量一定得满足以下任一否则编译出错这是java中对final这个关键字的限制 对于final修饰的使用                 ①使用时得赋值不然报错                 ②如果不在使用时就赋值就得在构造方法中赋值 2通用性问题 只适用于IoC容器框架如果移植到其他框架就无法使用 3单一设计原则属性注入过于简单地使用会导致滥用从而更容易地违背单一设计原则比如一个类设计出来就是单一职责不能既干那又干那 ✔属性注入的优点 1属性注入优点也就是操作简单只需在成员变量前加上注解即可完成对象注入并使用获取到的Bean对象 2Setter注入 对于set方法加上Autowired注解后spring会自动调用set方法从spring中获取Bean对象并注入到成员变量里去。 【注意】上述代码运行成功的前提条件是spring已经存进了Bean对象User不然对象注入也没得注入 。 ✔Setter注入的优点         1符合单一设计原理因为一个Setter方法就只针对一个对象 ✔Setter注入的缺点         1注入的对象可能被修改setter方法作为方法是可以被多次调用的那么就有被修改的风险         2不能注入一个不可变的变量 3构造方法注入 构造方法注入跟上述属性注入和Setter注入使用方法差不多都是在一个类中对另一个类对象进行注入。         此处是在构造方法前加上Autowired注解spring就会自动调用该构造方法从容器中获取对应的Bean对象并传进去。 UserController类  Controller public class UserController {//构造方法注入private User user;Autowiredpublic UserController(User user) {this.user user;}public User getUser() {return user;}public void function(){System.out.println(UserController!);System.out.println(user.getName());} } User类  public class User {private int id;private String name;public int getId() {return id;}public void setId(int id) {this.id id;}public String getName() {return name;}public void setName(String name) {this.name name;}Overridepublic String toString() {return User{ id id , name name \ };} } 启动类 public class App3 {public static void main(String[] args) {ApplicationContext context new ClassPathXmlApplicationContext(spring_config.xml);UserController controller context.getBean(userController, UserController.class);controller.function();} } 构造方法注入和其他两个注入最大的区别是         如果当前类只有一个构造方法注入可以省略Autowiredspring依然会去找对应的Bean对象进行注入但当出现多个构造方法注入时就不能省略了spring不知道要对具体哪个进行构造方法注入。 Controller public class UserController {//构造方法注入private User user;// Autowired //即使省略了还是可以进行构造方法注入public UserController(User user) {this.user user;}public User getUser() {return user;}public void function(){System.out.println(UserController!);System.out.println(user.getName());} } 而且需要注意的是一个类中有且只能有一个被Autowired注解修饰的构造方法否则spring不知道要对哪个构造方法进行对象注入。如果加多了就会报错。spinrg规定只能在一个类中使用一次Autowired修饰。         构造方法的注入可以一次性注入多个对象但切记注入的对象一定得是spring中有的这是最基本的要求如果spring中都没有该Bean对象那谁传一个参数过去呢 ①构造方法的优点          1可以使用注入被final修饰的对象这是因为不可变量要想能使用                 ①在声明的时候就得进行赋值否则报错                 ②在构造方法中进行赋值这两种规范都是jdk的要求即使是spring也得服从 而构造方法注入正好满足不可变量要想使用的第二个条件由于构造方法是在类加载的时候就调用也就是说在在类加载的时候就执行构造方法注入因此就会直接从spring中获取Bean对象注入到该不可变量中给它赋值了。         2注入的对象依赖对象一定会完全初始化因为依赖对象是在构造方法中执行的而构造方法是在类加载的时候就执行 因此依赖对象会在第一时间就初始化完成。         3通用性好不仅适用于IOC还能使用多种框架这是因为构造方法是jdk支持的最底层的框架所以更换任何框架都是适用的。         4注入的对象不会被修改因为在一个类的生命周期中构造方法只调用一次。 ②构造方法的缺点         构造方法的缺点也很明显它可以进行多个注入这就不满足单一设计原则了。 4Resource注解 ✔Resource注解和Autowired注解功能一样都是能进行对象注入这两个注解各有各的优点、缺点可以根据场景需求使用其中一个进行对象注入。 用法和Autowired一样只是没有构造方法注入 Resource和Autowired的区别  指定spring中的Bean对象名称从而获取Bean对象这也是Autowired无法做到的它里面就只有一个属性required默认为true表示当前注解一定得注入一个存在的Bean对象否则会报错。 Resource和Autowired出身不同Resource是jdk提供的而Autowired是spring提供的Resource只能进行属性注入和Setter注入无法进行构造方法注入这是因为Resource比较特殊注入的时机比较慢是在对象创建后才注入而构造方法注入是类加载的时候就注入了因此无法Resource无法用于构造方法注入 3.7、多个同类型Bean对象的指定获取  当spring存入了多个同类型的Bean对象时如果只是使用Autowired进行对象注入很有可能无法准确拿到想要的Bean对象 Autowired对象注入首先会根据类名去Spring中寻找符合的类型的Bean对象但由于Spring当中存在多个同类型Bean对象因此就会按变量名去寻找但有时注入对象的命名跟Spring当中的Bean对象没有一个是匹配的那么此时就很麻烦在不更改注入对象命名的前提下没法拿到对应的Bean对象。 以下述为例Spring 当中存入两个User类型的Bean对象命名分别是user1、user2 Service public class UserService {Beanpublic User user1(){User user new User();user.setName(1);return user;}//使用方法注解存储Bean对象Beanpublic User user2(){User user new User();user.setName(2);return user;}} 此处通过属性注入获取Bean对象 Controller public class UserController {Autowiredprivate User user;public void function(){System.out.println(UserController!);System.out.println(user.getName());} } 启动类 public class App3 {public static void main(String[] args) {ApplicationContext context new ClassPathXmlApplicationContext(spring_config.xml);UserController controller context.getBean(userController, UserController.class);controller.function();} } 启动类中调用UserController类中注入的User对象发现没有找到对应的对象。这是因为在进行对象注入的时候没有在spring当中找到User类名为user的Bean对象前面存入spring中的对象有User user1User user2没有一个是User user。所以此处要获取到准确的Bean对象需要在属性注入处进行指定。 1 使用Qualify  由于Autowired不像Resource一样有多个参数可以设置但spring引入了另外一个注解来辅助Autowired去指定Bean对象也就是Qualify注解 Qualify(value) Controller public class UserController {AutowiredQualifier(value user1)private User user;public void function(){System.out.println(UserController!);System.out.println(user.getName());} } 2使用Resource  通过设置Resource中的属性name来指定Bean对象 Controller public class UserController {Resource(name user2)private User user;public void function(){System.out.println(UserController!);System.out.println(user.getName());} } 三、Bean的作用域和生命周期 1、Bean作用域的理解 对于传统作用域能想到的就是例如一个方法中定义了一个局部变量a那么该变量a的作用域就只是作用在当前方法中出了这个方法就没有用了除非将它作为返回值或参数传递出去。         而Bean作用域不一样它表示的是Bean对象在Spring当中的某一种行为模式比如 单例作用域单例行为模式一个Bean对象在spring当中有且仅有一份共享的如果谁使用了这个Bean对象并对其进行修改其他方法去获取时就会发现该对象发生了修改。 UserController类  Controller public class UserController {Resource(name user1)private User user;public void function(){//此处声明一个新变量指向注入的Bean对象User user1 user;user1.setName(修改了);System.out.println(UserController);System.out.println(user1.getName());} } UserRepository类  Repository public class UserRepository {public User user;AutowiredQualifier(value user1)public void setUser(User user){this.user user;}public void function(){System.out.println(UserRepository);System.out.println(user.getName());} } 启动类  public class App3 {public static void main(String[] args) {ApplicationContext context new ClassPathXmlApplicationContext(spring_config.xml);UserController controller context.getBean(userController, UserController.class);UserRepository repository context.getBean(userRepository,UserRepository.class);//获取spring中Bean对象user1controller.function(); //此处里面重新声明了一个user1repository.function(); //使用的是原spring中Bean对象user//得到的结果理想是//UserController//修改了//UserRepository//1} } 得到的真实结果是 上述UserController类中对属性注入后的user又重新声明了一个新变量user1指向里面的user。但根据java语法来说其实声明的user1是指向Bean对象本身的只是更改了指向方而已因此在里面对user1进行属性修改会影响到Bean对象本身。 又由于Bean中的单例作用域所有的同一个Bean对象都是共享有一方对其进行修改会影响到其他方的获取跟实际原对象信息不一样。 2、Bean的作用域 Bean的作用域一共可以分为五种分别是 singleton单例作用域prototype原型作用域又称为多例作用域application全局作用域request请求作用域session会话作用域websocketHTTP WebSocket作用域 上述的application、request、session、websocket作用域都是属于spring MVC中的。只适用于web环境中Spring ApplicationContext中有效。 2.1、singleton作用域 singleton作用域在该作用域下IoC容器中的Bean只存在一个实例且无论是通过ApplicationContext获取spring上下文从而获取Bean对象还是使用对象注入的方式获取的Bean对象都是共享的有且仅有一份如果有一个类注入使用修改该Bean对象另外一个类去使用时该Bean对象就已经发生修改了。 适用场景通常得是无状态的Bean对象才使用该作用域。无状态表示该Bean对象不发生任何属性修改 【注意】Spring存储的Bean对象默认是 singleton作用域 2.2、prototype作用域 prototype作用域称为原型作用域又称为多例作用域根据意思就知道跟singleton作用域恰好相反了单例作用域中的Bean对象是共享的而原型作用域中的Bean对象则不是在spring中每次获取的Bean对象都是创建的一个新的实例也就是说每次获取的Bean对象都是新的。就不会说A类修改a这个Bean对象B类去获取这个a对象该对象会发生修改原型模式中是不存在这种情况。 适用场景通常得是有状态的Bean对象才使用该作用域 2.3、application作用域 application作用域在一个Http servlet context下定义了一个Bean对象是全局的。但跟singleton又不一样application作用域可以在多个类中创建获取上下文因此这些类中上下文中的Bean对象又不是共享的一个上下文中就有一个多个上下文就有多个只是在当前类中创建的上下文定义的Bean对象才是共享的。singleton作用域的Bean是spring容器中有且仅有一份且彼此共享。 application作用域是作用于servlet容器且是属于spring web的作用域 2.4、request作用域 request作用域相比于prototype作用域而言prototype作用域是每访问一次Bean对象就创建一个新的实例而request作用域是每收到一次Htpp请求就创建一个实例有可能收到的请求中包含多个Bean对象的访问但一次请求就只创建一次实例跟prototype差别还是挺大的 ⼀次http的请求和响应的共享Bean且仅支持在 Spring MVC 中使用 2.5、session作用域 session作用域每一次http session都会创建一次实例第一次登陆完成后创建session之后登陆都是用的这个会话当把会话关了重新创建会话这时就算重新登陆一次账号此时获取的Bean对象是不一样的因为删掉原有会话重新创建的session id是跟原来不一样的【session不一样- Bean对象也就不一样了。】 用户回话的共享Bean, ⽐如记录⼀个⽤户的登陆信息且仅支持在 Spring MVC中 使用 2.6、websocket作用域 在⼀个HTTP WebSocket的生命周期中定义⼀个Bean实例对于网络聊天聊天双方不可以用http进行通信因为发送http请求是由服务器接受并被动的返回响应 而用户双方的聊天一定是双向发送双方都可以接受和发送就得用到websocket双方都是客户端WebSocket的每次会话中保存了⼀个Map结构的头信息将用来包裹客户端消息头。第⼀次初始化后直到WebSocket结束都是同⼀个Bean限定Spring WebSocket中使⽤ 2.7、设置Bean对象作用域 使用Scopre来设置Bean对象的作用域设置作用域的方法有两种 1直接设置Scope( )字符串参数直接指定作用域名比如singleton、prototype 2枚举设置Scope(ConfigurableBeanFactory.xxxx)xxx为一个字符串如下图两个 String SCOPE_SINGLETON singleton; String SCOPE_PROTOTYPE prototype; 下述演示修改将存入的Bean对象设置为 原型模式prototype BeanUser类 Controller //使用类注解将该对象存入spring当中 Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public class BeanUser {private String name Bean;private int id 1;public String getName() {return name;}public void setName(String name) {this.name name;}public int getId() {return id;}public void setId(int id) {this.id id;} }BeanService类对Bean对象进行修改 Service public class BeanService {Autowiredprivate BeanUser beanUser;public void function(){System.out.println(原Bean,idbeanUser.getId()namebeanUser.getName());BeanUser beanUser1 beanUser;beanUser1.setId(2);beanUser1.setName(Bean);System.out.println(BeanService对bean对象修改后,id beanUser1.getId();name beanUser1.getName());System.out.println(哈希地址beanUser1);System.out.println();} } BeanService2类输出Bean对象的属性看是否是同一个 Service public class BeanService2 {Autowiredprivate BeanUser beanUser;public void function(){System.out.println(BeanService只是获取Bean对象,id beanUser.getId();name beanUser.getName());System.out.println(哈希地址beanUser);} }启动类 public class App {public static void main(String[] args) {ApplicationContext context new ClassPathXmlApplicationContext(spring_config.xml);BeanService beanService context.getBean(beanService,BeanService.class);beanService.function();BeanService2 beanService2 context.getBean(beanService2,BeanService2.class);beanService2.function();} }通过输出结果可以知道确实prototype作用域下每次获取的Bean对象都是重新创建的一个新实例。 3、Spring的执行流程 1首先通过获取Spring Context上下文来启动容器 2配置spring中的xml文件 3Bean的初始化配置xml文件中的Bean、配置扫描包路径并加载看包路径下的类是否加上了注解 4将Bean对象存到到容器中 5将Bean对象注入/装配到类中使用它 6销毁Spring 4、Bean的生命周期 Bean的生命周期是Bean从创建到销毁的这一过程。Bean的生命周期执行流程相比于Spring的执行流程大有不同Spring的执行流程是框架的而Bean的执行流程属于是Spring执行流程中的一个环节 Bean的生命周期可以分为5个部分 1. Bean的实例化分配内存空间 2. 将当前类依赖的 Bean 属性进行注入和装配 3. Bean的初始化该过程又可以分为以下几个步骤【Bean对象的重命名是发生在初始化中的。Beanvalue】 实现了各种 Aware 通知的方法如 BeanNameAware、BeanFactoryAware、ApplicationContextAware 的接口方法给Bean起一个名称为一个事件设置完名称之后就会有一个通知BeanNameAware执行BeanPostProcessor初始化的前置方法初始化的前置方法也就是在初始化之前的/构造方法之前执行的方法执行Bean的初始化方法执⾏ PostConstruct 初始化⽅法依赖注⼊操作之后被执⾏执行BeanPostProcessor初始化的后置方           4. 使用Bean 在程序当中使用Bean对象 5. 销毁Bean使用PreDestory、DisposableBean 接⼝⽅法、destroy-method 【注意】 1实例化不等于初始化实例化分配内存空间将之前自变量变成具体的内容根据内存地址可以拿到它。 2实例化和属性设置是 Java 级别的系统“事件”其操作过程不可人工干预和修改而初始化是给开发者提供的可以在实例化之后类加载完成之前进行自定义“事件”处理。 演示Bean对象生命周期的过程 spring的配置文件 ?xml version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contenthttp://www.springframework.org/schema/contextxsi:schemaLocationhttp://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.xsdcontent:component-scan base-packagecom.test/content:component-scanbean idbeanService classcom.test.service.BeanService init-methodinitMethod/bean /beans BeanService类此处为Bean的实例化属性设置、Bean对象初始化的过程 配置Bean对象初始化的方法有两种 1使用PostConstruct注解 2在xml配置文件中配置 Bean对象中的 init-method属性指定一个方法为初始化方法该属性的值对应初始化方法的方法名 这两种方式创建的Bean的初始化方法有优先之分注解配置的执行要快于xml中配置的。init method属于是旧版本用的后面才使用的PostConstructPostConstruct优先级高于init method创建用新不用旧 Service public class BeanService implements BeanNameAware {//实现BeanNameAware接口重写setBeanName通知方法Overridepublic void setBeanName(String s) {System.out.println(执行Bean对象的Aware通知s);}//进行Bean对象的初始化 // PostConstruct // public void function(){ // //执行Bean对象初始化方法 // System.out.println(PostConstruct执行Bean对象初始化方法); // }//也可以使用xml中配置一个初始化方法public void initMethod(){System.out.println(init-执行Bean对象初始化方法);}public void useBean(){System.out.println(使用Bean对象);}PreDestroypublic void destory(){System.out.println(执行Bean对象的销毁);}} BeanProcessor类 将Bean对象的初始化前置和后置方法单独定义在一个类中使用因为一般前置和后置方法是所有Bean对象通用使用的不是单独为一个Bean对象所服务的(我为人人)所以这两个方法不能写在某个具体的 Bean 中否则这两个方法不会执行 Service public class BeanService implements BeanNameAware {Overridepublic void setBeanName(String s) {System.out.println(执行Bean对象的Aware通知s);}//进行Bean对象的初始化 // PostConstruct // public void function(){ // //执行Bean对象初始化方法 // System.out.println(PostConstruct执行Bean对象初始化方法); // }//也可以使用xml中配置一个初始化方法public void initMethod(){System.out.println(init-执行Bean对象初始化方法);}public void useBean(){System.out.println(使用Bean对象);}PreDestroypublic void destory(){System.out.println(执行Bean对象的销毁);}} 启动类 public class App {public static void main(String[] args) {//此处使用ConfigurableApplicationContext来获取spring中的上下文因为ApplicationContext类中没有close()---处理spring的销毁方法ConfigurableApplicationContext context new ClassPathXmlApplicationContext(spring_config.xml);BeanService beanService context.getBean(beanService,BeanService.class);beanService.useBean(); //使用Beancontext.close(); //销毁Spring} } 注意Bean的注入和初始化的执行顺序不可以交换         一般我们总会认为无论是对于要使用的变量还是对象都是先初始化后再使用。 但对于Spring来说Bean对象一定得先注入/装配到一个类中才可以进行初始化。         因为Bean对象的初始化过程中可能会使用到Bean对象本身但此时如果是先初始化后注入初始化方法中拿到的Bean对象就是一个空对象从而引发 “空指针异常”所以应该对于Bean的生命周期中一定得先注入了Bean对象后才可以初始化。 对于spring的基础操作总结到这里就结束了上述文字量较多但讲的都是很基础如果有什么错误希望各路大神可以指点一二。
http://www.pierceye.com/news/398586/

相关文章:

  • 怎样进入网站的后台视频网站建设方案书
  • 家具网站开发报告北斗导航2022最新版手机版
  • 好看的食品网站app图片怎么制作
  • 杭州做外贸网站wordpress给用户发送邮件
  • 政务服务 网站 建设方案软件外包平台哪家好
  • 上海千途网站建设网站建设 中企动力长沙
  • 网站建设产品介绍烟台定制网站建设电话
  • 公司内部网站设计客户关系管理策略
  • 个人开发网站要多少钱梅州市城乡建设局网站
  • 外贸公司网站案例建设银行报考网站
  • 网站设计建设步骤做暖网站
  • dw如何做网站界面全网推广外包公司
  • 企业网站数据库建设菠菜网站
  • 网站功能优化的方法营销型网站建设集装箱液袋
  • 建设资讯网站厦门网站建设哪家强
  • 惠阳网站设计开发图片做多的网站是哪个
  • 医院网站建设公司价格低本地网站搭建视频教程
  • 黑客攻击的网站网站开发需要多少钱app
  • 海南建设厅评审网站织梦网站加网站地图
  • 清迈城市建设网站外贸搜索网站
  • 怎样做网站公司网站建设维护管理
  • 伊犁网站制作珠海做网站的公司
  • 乐山市规划和建设局网站房地产基础知识
  • 网站给假冒伪劣产品做推广鞍山网站制作一般需要多少钱
  • 番禺网站开发哪里好ppt模板免费下载完整版免费简约
  • 哪个公司做企业网站好济南网站优化推广公司电话
  • 深圳网站建设外包公司网站流量提供商
  • 网站建设优化服务信息wordpress下载类插件
  • 深圳做网站google推广百度优化是什么
  • 网站开发技术服务费分享经济网站怎么建设