范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

一篇文章带你掌握主流基础框架Spring

  这篇文章中我们将会介绍Spring的框架以及本体内容,包括核心容器,注解开发,AOP以及事务等内容
  那么简单说明一下Spring的必要性: Spring技术是JavaEE开发的必备技能,企业开发技术选型率高达90%! Spring可以帮助简化开发,降低企业级开发的复杂度 Spring可以进行框架整合,高效整合其他技术,提高企业级应用开发与运行效率
  Spring的核心内容: Ioc技术 DI技术 AOP 事务处理
  Spring可进行的框架整合: MaBatis MyBatis-plus Struts Struts2 Hibernate
  在接下来的文章中,我们会学习Spring的框架思想,学习Spring的基本操作,结合案例熟练掌握 温馨提醒:在学习本篇文章前请先学习JavaWeb相关内容
  (HTTP,Tomcat,Servlet,Request,Response,MVC,Cookie,Session,Ajax,Vue等内容) 初识Spring
  官网:Spring | Home
  Spring发展至今已经形成了一套开发的生态圈,Spring提供了相当多的项目,每个项目用于完成特定功能
  我们常用的主流技术包括有: Spring Framework:Spring框架 Spring Boot:Spring简化代码开发 Spring Cloud:Spring分布设计 Spring FrameWork系统架构
  在系统学习Spring之前,我们需要先来了解FrameWork系统结构 Spring FrameWork是Spring生态圈中最基本的项目,是其他项目的根基
  我们现在所使用的Spring FrameWork是4.0版本,已经趋于稳定
  下面我们对架构图进行解释: Core Container:核心容器 AOP:面向切面编程 Aspects:AOP思想实现 Data Access:数据访问 Data Intergration:数据集成 Web:Web开发 Test:单元测试与集成测试
  我们可以在官方中获得如此评价: 强大的基于 JavaBeans 的采用控制反转(Inversion of Control,IoC)原则的配置管理,使得应用程序的组建更加快捷简易。 数据库事务的一般化抽象层,允许插件式事务管理器,简化事务的划分使之与底层无关。 一个可用于从 applet 到 Java EE 等不同运行环境的核心 Bean 工厂。 核心概念介绍
  首先我们思索一下我们之前的业务层与数据层: // 数据层接口 public interface BookDao {     public void save(); } // 数据层实现 public class BookDaoImpl implements BookDao {     public void save() {         System.out.println("book dao save ...");     } } // 业务层接口 public interface BookService {     public void save(); } // 业务层实现 public class BookServiceImpl implements BookService {     private BookDao bookDao;      public void save() {         bookDao.save();     }  }
  如果我们修改BookDaoImpl内容,那么相对应的业务层实现中的bookDao的new实现也要进行修改,甚至下方方法的对象也要进行修改 Spring使用前问题
  代码书写现状: 耦合度偏高
  解放方案: 使用对象时,在程序中不要主动使用new产生对象,转换为由外部提供对象 Spring思想以及实现
  IoC(Inversion of Control)控制反转思想: 使用对象时,由主动new创建对象转换为由外部提供对象 此过程中对象创建控制权由程序转移到外部,被称为控制反转
  DI(Dependency Injection)依赖注入: 在容器中建立Bean与Bean之间的依赖关系和整个过程,被称为依赖注入
  Spring技术对Ioc思想进行了实现: Spring提供了一个容器,被称为Ioc容器,用来充当IoC思想的外部 IoC容器负责对象的创建,初始化等一系列工作,被创建和管理的对象在IoC容器中被称为Bean // 数据层实现 public class BookDaoImpl implements BookDao {     public void save() {         System.out.println("book dao save ...");     } } // IoC容器 /* 包含 dao service 两者可以建立连接 */ // 业务层实现 public class BookServiceImpl implements BookService {     private BookDao bookDao;      public void save() {         bookDao.save();     }  }
  目的:充分解耦 IoC:使用IoC容器管理bean DI:在IoC容器内将有依赖关系的bean进行关系绑定
  最终效果: 使用对象不仅可以直接从IoC容器中获取,还可以将已获得的Bean之间绑定依赖关系 IoC入门
  首先我们需要明白IoC的使用规则: IoC负责管理什么:Service和Dao 如何被管理的对象告知IoC容器:(配置) 被管理的对象交给IoC容器,如何获得IoC容器:(接口) IoC容器得到之后,如何获得Bean:(接口方法) 使用Spring所需要导入的坐标:(pom.xml)
  下面我们给出IoC入门的详细步骤: 创建Maven项目,在pom.xml中导入坐标               org.springframework       spring-context       5.2.10.RELEASE         创建Spring.xml的配置包(applicationContext.xml,导入坐标后xml中更新该XML) <?xml version="1.0" encoding="UTF-8"?>                               主函数 package com.itheima;  import com.itheima.dao.BookDao; import com.itheima.service.BookService; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;  public class App2 {     public static void main(String[] args) {         //3.获取IoC容器         ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");                  //4.获取bean(根据bean配置id获取) 		//BookDao bookDao = (BookDao) ctx.getBean("bookDao"); 		//bookDao.save();                  // 注意:需要类型转化          BookService bookService = (BookService) ctx.getBean("bookService");         bookService.save();      } } DI入门
  首先我们需要明白DI的使用规则: 基于IoC管理bean Service中使用new形式创建Dao对象是否保留:(否) Service中需要Dao对象如何进入到Service中:(提供方法) Service与Dao之间的关系如何描述:(配置)
  下面我们给出DI入门的详细步骤(基于IoC入门): 删除new方法 public class BookServiceImpl implements BookService {     //5.删除业务层中使用new的方式创建的dao对象     private BookDao bookDao;      public void save() {         System.out.println("book service save ...");         bookDao.save();     }  } 创建对象的set方法 public class BookServiceImpl implements BookService {     //5.删除业务层中使用new的方式创建的dao对象     private BookDao bookDao;      public void save() {         System.out.println("book service save ...");         bookDao.save();     }          //6.提供对应的set方法     public void setBookDao(BookDao bookDao) {         this.bookDao = bookDao;     } } 创建Dao和Service的连接 <?xml version="1.0" encoding="UTF-8"?>                                                          Bean整体介绍
  Bean是保存在IoC中的对象,我们通过配置的方式获得Bean
  下面我们从三个方面分别讲解Bean: bean基本配置
  首先我们先介绍bean本身性质:
  类别
  描述
  名称
  bean
  类型
  标签
  所属
  beans标签
  功能
  定义Spring核心容器管理对象
  格式
  属性列表
  id:bean的id,使用容器可以通过id值获得对应的bean,在一个容器中id值唯一
  class:bean的类型,即配置的bean的全路径类名
  范例
  然后我们介绍一下bean的别名:
  类别
  描述
  名称
  name
  类型
  标签
  所属
  bean标签
  功能
  定义bean的别名,可定义多个,使用逗号,分号,空格分隔
  范例
  正常情况下,使用id和name都可以获得bean,但推荐还是使用唯一id
  获得bean无论通过id还是name获取,如果无法找到则抛出异常NosuchBeanDefinitionException
  最后我们介绍一下bean的作用范围scope:
  类别
  描述
  名称
  scope
  类型
  标签
  所属
  bean标签
  功能
  定义bean的作用范围,可选范围如下:
  singleton:单列(默认)
  prototype:非单列
  范例
  这里的scope指产生对象的数量
  我们的scope在默认情况下是singleton,因为很多对象只需要创建一次,多次创建会导致内存膨胀
  合适交给容器进行管理的bean(singleton):
  表现层对象业务层对象数据层对象工具对象
  不合适交给容器进行管理的bean(prototype):
  封装实体的域对象(带有状态的bean) bean实例化
  bean的实例化通常分为四种方法,我们在下面一一介绍: 构造方法(常用)
  我们需要在数据类中提供构造方法,配置条件中不需要改变 // 数据类  public class BookDaoImpl implements BookDao {      public BookDaoImpl() {         System.out.println("book dao constructor is running ....");     }      public void save() {         System.out.println("book dao save ...");     }  } <?xml version="1.0" encoding="UTF-8"?>              
  若无参构造方法不存在,则抛出异常BeanCreationException 静态工厂(了解)
  我们在之前的案例中存在有对象工厂的说法,我们可以设置工厂并调用其方法得到bean // 静态工厂 package com.itheima.factory;  import com.itheima.dao.OrderDao; import com.itheima.dao.impl.OrderDaoImpl; //静态工厂创建对象 public class OrderDaoFactory {     public static OrderDao getOrderDao(){         System.out.println("factory setup....");         return new OrderDaoImpl();     } } <?xml version="1.0" encoding="UTF-8"?>               实例工厂(了解)
  和静态工厂相同,但不同点是方法不是静态,我们需要提前创建一个bean // 实例工厂 package com.itheima.factory;  import com.itheima.dao.UserDao; import com.itheima.dao.impl.UserDaoImpl; //实例工厂创建对象 public class UserDaoFactory {     public UserDao getUserDao(){         return new UserDaoImpl();     } }  <?xml version="1.0" encoding="UTF-8"?>                         FactoryBean(重要实用)
  除了我们之前自己定义的工厂外,Spring提供了一种官方版本的FactoryBean // FactoryBean工厂(需接口,< >中填写数据类接口) package com.itheima.factory;  import com.itheima.dao.UserDao; import com.itheima.dao.impl.UserDaoImpl; import org.springframework.beans.factory.FactoryBean; //FactoryBean创建对象 public class UserDaoFactoryBean implements FactoryBean {     //代替原始实例工厂中创建对象的方法          // 返回创建对象类型为UserDaoImpl()     public UserDao getObject() throws Exception {         return new UserDaoImpl();     }      // 这里填写接口类型     public Class<?> getObjectType() {         return UserDao.class;     }      // 可以修改来修改其scope属性     public boolean isSingleton() {         return false;     } } <?xml version="1.0" encoding="UTF-8"?>               bean生命周期
  我们先来接单介绍生命周期相关概念: 生命周期:从创建到消亡的完整过程 bean生命周期:bean从创建到销毁的整体过程 bean生命周期控制:在bean创建后到销毁前做一些事情
  接下来我们介绍生命周期控制方法: 数据层提供控制方法
  由数据层提供方法,在xml配置文件中设置该方法 // 数据层 package com.itheima.dao.impl;  import com.itheima.dao.BookDao;  public class BookDaoImpl implements BookDao {          public void save() {         System.out.println("book dao save ...");     }          //表示bean初始化对应的操作     public void init(){         System.out.println("init...");     }     //表示bean销毁前对应的操作     public void destory(){         System.out.println("destory...");     }  }   <?xml version="1.0" encoding="UTF-8"?>                                        接口控制方法(了解)
  Spring为创建提供了两个接口,我们只需要继承并实现该方法即可 package com.itheima.service.impl;  import com.itheima.dao.BookDao; import com.itheima.service.BookService; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean;  // InitializingBean,DisposableBean 分别对应afterPropertiesSet,destroy方法,代表创建和销毁 public class BookServiceImpl implements BookService, InitializingBean, DisposableBean {     private BookDao bookDao;      public void setBookDao(BookDao bookDao) {         System.out.println("set .....");         this.bookDao = bookDao;     }      public void save() {         System.out.println("book service save ...");         bookDao.save();     }      public void destroy() throws Exception {         System.out.println("service destroy");     }      public void afterPropertiesSet() throws Exception {         System.out.println("service init");     } }  <?xml version="1.0" encoding="UTF-8"?>                                      
  我们需要提及一下bean的销毁时机:(了解即可) 因为默认情况下,我们的bean不会被销毁,因为虚拟机会直接退出,ClassPathXmlApplicationContext会被忽略销毁过程
  所以如果我们希望销毁bean观察到destroy的实现,需要手动关闭: 手动关闭容器方法: package com.itheima;  import com.itheima.dao.BookDao; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;  public class AppForLifeCycle {     public static void main( String[] args ) {         // 注意:这里需要采用ClassPathXmlApplicationContext作为对象,因为只有这个类才具有close方法         ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");          BookDao bookDao = (BookDao) ctx.getBean("bookDao");         bookDao.save();         //关闭容器         ctx.close();     } }  注册关闭钩子,在虚拟机退出前先关闭容器再推出虚拟机 package com.itheima;  import com.itheima.dao.BookDao; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;  public class AppForLifeCycle {     public static void main( String[] args ) {         ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");          BookDao bookDao = (BookDao) ctx.getBean("bookDao");         bookDao.save();         //注册关闭钩子函数,在虚拟机退出之前回调此函数,关闭容器         ctx.registerShutdownHook();     } }  最后我们统计一下整体生命周期:
  初始化容器:创建对象(分配内存)->执行构造方法->执行属性注入(set操作)->执行bean初始化方法使用bean:执行业务操作关闭/销毁容器:执行bean销毁方法 依赖注入方式
  首先我们要知道类中传递数据的方法有两种: 普通方法(Set方法) 构造方法
  然后我们要知道数据的类型大体分为两种: 引入类型(数据层) 简单类型(基本数据类型和String)
  所以我们把依赖注入方式分为四种: setter注入简单类型引用类型 构造器注入简单类型引入类型 setter注入简单类型
  首先我们需要在bean种定义简单类型属性并提供可以访问的set方法 package com.itheima.dao.impl;  import com.itheima.dao.BookDao;  public class BookDaoImpl implements BookDao {      private String databaseName;     private int connectionNum;     //setter注入需要提供要注入对象的set方法     public void setConnectionNum(int connectionNum) {         this.connectionNum = connectionNum;     }     //setter注入需要提供要注入对象的set方法     public void setDatabaseName(String databaseName) {         this.databaseName = databaseName;     }      public void save() {         System.out.println("book dao save ..."+databaseName+","+connectionNum);     } }
  然后在配置中使用property标签value属性注入简单类型数据 <?xml version="1.0" encoding="UTF-8"?>                                                                  setter注入引用类型
  首先我们需要在bean种定义引用类型属性并提供可以访问的set方法 package com.itheima.service.impl;  import com.itheima.dao.BookDao; import com.itheima.dao.UserDao; import com.itheima.service.BookService;  public class BookServiceImpl implements BookService{     private BookDao bookDao;     private UserDao userDao;     //setter注入需要提供要注入对象的set方法     public void setUserDao(UserDao userDao) {         this.userDao = userDao;     }     //setter注入需要提供要注入对象的set方法     public void setBookDao(BookDao bookDao) {         this.bookDao = bookDao;     }      public void save() {         System.out.println("book service save ...");         bookDao.save();         userDao.save();     } }
  然后在配置中使用property标签ref属性注入引用类型数据 <?xml version="1.0" encoding="UTF-8"?>                                                                                                    构造器注入简单类型(了解)
  在bean中定义简单类型属性并提供可访问的set方法 public class BookDaoImpl implements BookDao{ 	private int connectionNumber;          pubilc void setConnectionNumber(int connectionNumber){ 		this.connectionNumber = connectionNumber;     } }
  配置中使用constructor-arg标签value属性注入简单类型数据 <?xml version="1.0" encoding="UTF-8"?>                根据构造方法参数名称注入                       构造器注入引用类型(了解)
  在bean中定义引用类型属性并提供可访问的构造方法 public class BookDaoImpl implements BookDao{ 	private BookBao bookBao;          pubilc void setConnectionNumber(int connectionNumber){ 		this.bookBao = bookBao;     } }
  配置中使用constructor-arg标签ref属性注入简单类型数据 <?xml version="1.0" encoding="UTF-8"?>                                  构造器注入参数配置问题(了解)
  在前面我们已经介绍了构造器的注入方法
  但如果我们在bean中的数据名称发生改变,配置就不再适配,所以提供了一些方法来解决参数配置问题: 配置中使用constructor-arg标签type属性设置按形参类型注入 	              根据构造方法参数类型注入                                                           配置中使用constructor-arg标签index属性设置按形参类型注入                                                                             依赖注入方式选择
  依赖注入方式有以下选择标准: 强制依赖使用构造器进行,使用setter注入有概率不进行注入导致null对象出现 可选依赖使用setter注入进行,灵活性高 Spring框架倡导使用构造器,第三方框架内部大多数采用构造器注入的形式进行数据初始化,相对严谨 如果有必要可以两者并用,使用构造器注入完成强制依赖的注入,使用setter注入完成可选依赖的注入 实际开发中根据情况分析,如果受控对象没有提供setter方法则只能采用构造器注入 自己开发的模块尽量推荐setter注入 依赖自动装配
  在前面我们学习了手动注入的方法,但Spring其实为我们提供了一种依赖自动装配的语法: IoC容器根据bean所依赖的资源在容器中自动查找并注入bean中的过程称为自动装配
  自动装配方式: 按类型(常用) 按名称 按构造方法 不启用
  自动装配语法: <?xml version="1.0" encoding="UTF-8"?>                    依赖自动装配特征:
  自动装配用于引用类型注入,不能对简单类型进行操作使用按类型装配时(byType)必须保障容器中相同类型的bean唯一,推荐使用使用按名称装配时(byName)必须保障容器中具有指定名称的bean,因变量名与配置耦合,不推荐使用自动装配优先级低于setter注入和构造器注入,同时出现时,自动装配配置失效 依赖集合注入
  除了基本类型和引入类型外,我们有时也需要注入集合
  下面我们简单介绍一下结合的注入: // 数据类   package com.itheima.dao.impl;  import com.itheima.dao.BookDao;  import java.util.*;  public class BookDaoImpl implements BookDao {      private int[] array;      private List list;      private Set set;      private Map map;      private Properties properties;         public void setArray(int[] array) {         this.array = array;     }      public void setList(List list) {         this.list = list;     }      public void setSet(Set set) {         this.set = set;     }      public void setMap(Map map) {         this.map = map;     }      public void setProperties(Properties properties) {         this.properties = properties;     }         public void save() {         System.out.println("book dao save ...");          System.out.println("遍历数组:" + Arrays.toString(array));          System.out.println("遍历List" + list);          System.out.println("遍历Set" + set);          System.out.println("遍历Map" + map);          System.out.println("遍历Properties" + properties);     } }    <?xml version="1.0" encoding="UTF-8"?>                                                               100                 200                 300                                                                      itcast                 itheima                 boxuegu                 chuanzhihui                                                                      itcast                 itheima                 boxuegu                 boxuegu                                                                                                                                                                              china                 henan                 kaifeng                              案例:数据源对象管理
  针对一个新的数据源对象,我们采用两步来创建bean(我们以druid为案例): 导入druid坐标 <?xml version="1.0" encoding="UTF-8"?>      4.0.0      com.itheima     spring_09_datasource     1.0-SNAPSHOT                            org.springframework             spring-context             5.2.10.RELEASE                                        com.alibaba             druid             1.1.16                               mysql             mysql-connector-java             5.1.47                配置数据源对象作为Spring管理的bean <?xml version="1.0" encoding="UTF-8"?>                                                                      案例:加载properties文件
  这个案例我们将会介绍如何加载properties文件,并将文件带入到property基本信息中
  我们大致将步骤分为以下三步: 开辟context命名空间: <?xml version="1.0" encoding="UTF-8"?>    使用context命名空间,加载指定properties文件    使用${}读取加载的属性值                                                 
  除了上述的基本操作,我们在context命名空间的使用中有很多需要注意的点: 不加载系统属性   加载多个properties文件   加载所有properties文件   加载properties文件标准格式    从类路径或jar包中搜索并加载properties文件   核心容器
  前面已经完成bean与依赖注入的相关知识学习,接下来我们主要学习的是IOC容器中的核心容器。
  这里所说的核心容器,大家可以把它简单的理解为ApplicationContext,接下来我们从以下几个问题入手来学习下容器的相关知识: 如何创建容器? 创建好容器后,如何从容器中获取bean对象? 容器类的层次结构是什么? BeanFactory是什么? 容器的创建方式
  案例中创建ApplicationContext的方式为(类路径下的XML配置文件): ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
  除了上面这种方式,Spring还提供了另外一种创建方式为(文件的绝对路径): ApplicationContext ctx = new FileSystemXmlApplicationContext("D:workspacespringspring_10_containersrcmainresourcesapplicationContext.xml"); Bean的三种获取方式
  方式一,就是目前案例中获取的方式: BookDao bookDao = (BookDao) ctx.getBean("bookDao");
  这种方式存在的问题是每次获取的时候都需要进行类型转换
  方式二: BookDao bookDao = ctx.getBean("bookDao",BookDao.class);
  这种方式可以解决类型强转问题,但是参数又多加了一个,相对来说没有简化多少。
  方式三: BookDao bookDao = ctx.getBean(BookDao.class);
  这种方式就类似我们之前所学习依赖注入中的按类型注入。必须要确保IOC容器中该类型对应的bean对象只能有一个。 容器类层次结构
  下面我们给出容器的层次图
  BeanFactory的使用
  使用BeanFactory来创建IOC容器的具体实现方式为: public class AppForBeanFactory {     public static void main(String[] args) {         Resource resources = new ClassPathResource("applicationContext.xml");         BeanFactory bf = new XmlBeanFactory(resources);         BookDao bookDao = bf.getBean(BookDao.class);         bookDao.save();     } }
  为了更好的看出BeanFactory和ApplicationContext之间的区别,在BookDaoImpl添加如下构造函数: public class BookDaoImpl implements BookDao {     public BookDaoImpl() {         System.out.println("constructor");     }     public void save() {         System.out.println("book dao save ..." );     } }
  如果不去获取bean对象,打印会发现: BeanFactory是延迟加载,只有在获取bean对象的时候才会去创建 ApplicationContext是立即加载,容器加载的时候就会创建bean对象 ApplicationContext要想成为延迟加载,只需要按照如下方式进行配置 <?xml version="1.0" encoding="UTF-8"?>    核心概念总结
  接下来我们对前面知识的一个总结,共包含如下内容: 容器相关BeanFactory是IoC容器的顶层接口,初始化BeanFactory对象时,加载的bean延迟加载 ApplicationContext接口是Spring容器的核心接口,初始化时bean立即加载 ApplicationContext接口提供基础的bean操作相关方法,通过其他接口扩展其功能 ApplicationContext接口常用初始化类ClassPathXmlApplicationContext(常用)FileSystemXmlApplicationContext bean相关
  依赖注入相关
  注解开发
  在上述的开发中,我们采用xml配置文件的形式来说依旧显得有些复杂
  这时我们就需要发挥Spring的优点:简化开发,通过注解来简化开发过程
  下面我们会通过多个方面将Bean逐步转化为注解 注解开发Bean
  在前面的内容中,我们的bean在xml配置文件中装配 <?xml version="1.0" encoding="UTF-8"?>                      
  在后期,我们的bean可以采用注解的形式,直接在实现类中注解表示为bean
  我们采用@Component定义bean,可以添加参数表示id,也可以不添加参数,后期我们采用class类的类型来进行匹配 package com.itheima.dao.impl;  import com.itheima.dao.BookDao; import org.springframework.stereotype.Component; import org.springframework.stereotype.Controller; import org.springframework.stereotype.Repository;  //@Component定义bean @Component("bookDao") public class BookDaoImpl implements BookDao {     public void save() {         System.out.println("book dao save ...");     } } package com.itheima.service.impl;  import com.itheima.dao.BookDao; import com.itheima.service.BookService; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service;  //@Component定义bean @Component public class BookServiceImpl implements BookService {     private BookDao bookDao;      public void setBookDao(BookDao bookDao) {         this.bookDao = bookDao;     }      public void save() {         System.out.println("book service save ...");         bookDao.save();     } }
  @Componenty延伸出了三种类型,在实现手法上是一致,但可以具体使用于各种类中(仅用于自我识别) @Controller:用于表现层bean定义 @Service:用于业务层bean定义 @Repository:用于数据层定义 package com.itheima.dao.impl;  import com.itheima.dao.BookDao; import org.springframework.stereotype.Component; import org.springframework.stereotype.Controller; import org.springframework.stereotype.Repository; //@Component定义bean //@Component("bookDao") //@Repository:@Component衍生注解 @Repository("bookDao") public class BookDaoImpl implements BookDao {     public void save() {         System.out.println("book dao save ...");     } } package com.itheima.service.impl;  import com.itheima.dao.BookDao; import com.itheima.service.BookService; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; //@Component定义bean //@Component //@Service:@Component衍生注解 @Service public class BookServiceImpl implements BookService {     private BookDao bookDao;      public void setBookDao(BookDao bookDao) {         this.bookDao = bookDao;     }      public void save() {         System.out.println("book service save ...");         bookDao.save();     } }
  但是,在上述情况下,即使我们将@Component的类定义为bean
  我们的xml文件是无法探测到的,所以我们需要配置相关扫描组件来扫描bean <?xml version="1.0" encoding="UTF-8"?>                    纯注解开发
  我们前面所提到的注解开发属于2.5的附属版本
  在Spring3.0版本,Spring就提供了纯注解开发模式,利用java类代替配置文件,开启了Spring快速开发时代
  在之前我们的xml配置文件是很繁琐的:   <?xml version="1.0" encoding="UTF-8"?>                      
  但是我们可以通过创建单独的类来表示配置文件: @Configuration:用于声明当前类为Spring配置类 @ComponentScan:用于扫描类文件(类似于) package com.itheima.config;  import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration;  //声明当前类为Spring配置类 @Configuration //设置bean扫描路径,多个路径书写为字符串数组格式 @ComponentScan({"com.itheima.service","com.itheima.dao"}) public class SpringConfig { } 注意:因为该类属于配置类,我们通常单列一个文件夹来表示
  常用文件夹:config
  命名规范:SpringConfig,UserConfig...
  因为我们的开发不再依靠于xml配置文件,所以在主函数中的Spring容器获得方式也发生了改变: package com.itheima;  import com.itheima.dao.BookDao; import com.itheima.service.BookService; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;  public class App {     public static void main(String[] args) {                  // 这是我们之前的获取方式,采用路径获取xml文件         // ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");                  // 这是新的获取方式,直接提供配置类的类型         // AnnotationConfigApplicationContext加载Spring配置类初始化Spring容器         ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);                  // 后面操作无需变化                  BookDao bookDao = (BookDao) ctx.getBean("bookDao");         System.out.println(bookDao);         //按类型获取bean         BookService bookService = ctx.getBean(BookService.class);         System.out.println(bookService);     } } 注解开发Bean作用范围与管理
  既然我们的Bean开发从xml转移到注解开发,那么一些配置设置同样发生改变
  首先我们介绍Scope范围的设置方式: @Scope:定义bean的作用范围 package com.itheima.dao.impl;  import com.itheima.dao.BookDao; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Repository;  import javax.annotation.PostConstruct; import javax.annotation.PreDestroy;  @Repository //@Scope设置bean的作用范围(singleton或prototype),可以不添加默认singleton @Scope("singleton") public class BookDaoImpl implements BookDao {      public void save() {         System.out.println("book dao save ...");     }  }
  然后我们介绍一下bean生命周期的init和destroy操作: @PostConstruct:定义init操作,表示构造后操作 @PreDestroy:定义destroy操作,表示销毁前操作 依赖注入(自动装配)
  在Spring3.0中,省略掉了前面繁琐的依赖注入,我们的bean依赖注入只留下了自动装配这一操作: 使用@Autowired注解开启自动装配模式(按类型) 当存在相同类型时,我们采用@Qualifier开启按名自动装配 package com.itheima.service.impl;  import com.itheima.dao.BookDao; import com.itheima.service.BookService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service;  @Service public class BookServiceImpl implements BookService {     //@Autowired:注入引用类型,自动装配模式,默认按类型装配     @Autowired     //@Qualifier:自动装配bean时按bean名称装配     @Qualifier("bookDao")     private BookDao bookDao;      public void save() {         System.out.println("book service save ...");         bookDao.save();     } } 注意:自动装配基于反射设计创建对象并暴力反射对应属性为私有属性初始化数据,因此无需提供setter方法
  注意:自动转配建议使用无参构造方法创建对象(默认),如果不提供对应构造方法,请提供唯一的构造方法
  注意:@Qualifier是基于@Autowired实现的,必须保证先有Autowired才能存在Qualifier
  除了上述的bean类型装配,我们的简单类型装配依旧存在: 我们采用@Value的形式来配置简单类型的值 package com.itheima.dao.impl;  import com.itheima.dao.BookDao; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Repository;  @Repository("bookDao") public class BookDaoImpl implements BookDao {     //@Value:注入简单类型(无需提供set方法)     @Value("123")     private String name;      public void save() {         System.out.println("book dao save ..." + name);     } }
  之所以使用@Value的形式配置,是因为我们的类型值不一定是由手动输入的,有可能来自于Properties资源: 首先我们需要在Springconfig中配置相关资源 package com.itheima.config;  import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource;  @Configuration @ComponentScan("com.itheima") //@PropertySource加载properties配置文件 @PropertySource({"jdbc.properties"}) public class SpringConfig { } 然后我们在数据层调用时,采用${}来匹配数据 package com.itheima.dao.impl;  import com.itheima.dao.BookDao; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Repository;  @Repository("bookDao") public class BookDaoImpl implements BookDao {     //@Value:注入简单类型(无需提供set方法)     @Value("${name}")     private String name;      public void save() {         System.out.println("book dao save ..." + name);     } } 注解开发第三方bean
  我们在实际开发中不仅仅需要对自己的bean进行管理,有时候可能需要引进其他的bean
  下面我们以Druid为例进行讲解: 首先在pom.xml中导入Druid坐标 <?xml version="1.0" encoding="UTF-8"?>     4.0.0    com.itheima   spring_14_annotation_third_bean_manager   1.0-SNAPSHOT                org.springframework       spring-context       5.2.10.RELEASE                 com.alibaba       druid       1.1.16           使用@Bean配置第三方Bean // 该bean同样属于config文件,我们同样放置在config文件夹下 // 在后续我们将会讲解如何进行连接  package com.itheima.config;  import com.alibaba.druid.pool.DruidDataSource; import com.itheima.dao.BookDao; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;  import javax.sql.DataSource;  public class JdbcConfig {          // 1.定义一个方法获得要管理的对象         // 2.添加@Bean,表示当前方法的返回值是一个bean     // @Bean修饰的方法,形参根据类型自动装配     @Bean     public DataSource dataSource(){         DruidDataSource ds = new DruidDataSource();         ds.setDriverClassName("com.mysql.jdbc.Driver");         ds.setUrl("jdbc:mysql://localhost:3306/spring_db");         ds.setUsername("root");         ds.setPassword("123456");         return ds;     } } 将独立的配置类加入核心配置(导入法) // SpringConfig  package com.itheima.config;  import com.alibaba.druid.pool.DruidDataSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import;  import javax.sql.DataSource;  @Configuration @ComponentScan("com.itheima") //@Import:导入配置信息(如果需要多个,同样采用{}数组形式) @Import({JdbcConfig.class}) public class SpringConfig { }  // JdbcConfig  package com.itheima.config;  import com.alibaba.druid.pool.DruidDataSource; import com.itheima.dao.BookDao; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;  import javax.sql.DataSource;  //@Configuration public class JdbcConfig {     //@Bean修饰的方法,形参根据类型自动装配     @Bean     public DataSource dataSource(){         DruidDataSource ds = new DruidDataSource(); 		// 配置信息         return ds;     } }
  注意:除了上述的导入法外还存在有其他方法,但导入法属于主流,因此我们不介绍其他流派,感兴趣的同学可以去查阅一下 注解开发为第三方导入资源
  我们的第三方bean也可能需要导入部分资源,下面我们进行简单介绍: 简单类型依赖注入 package com.itheima.config;  import com.alibaba.druid.pool.DruidDataSource; import com.itheima.dao.BookDao; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;  import javax.sql.DataSource;  //@Configuration public class JdbcConfig {          //1.定义一个方法获得要管理的对象     @Value("com.mysql.jdbc.Driver")     private String driver;     @Value("jdbc:mysql://localhost:3306/spring_db")     private String url;     @Value("root")     private String userName;     @Value("root")     private String password;          //2.添加@Bean,表示当前方法的返回值是一个bean     //@Bean修饰的方法,形参根据类型自动装配     @Bean     public DataSource dataSource(){         DruidDataSource ds = new DruidDataSource();         ds.setDriverClassName(driver);         ds.setUrl(url);         ds.setUsername(userName);         ds.setPassword(password);         return ds;     } }  依赖类型依赖注入 package com.itheima.config;  import com.alibaba.druid.pool.DruidDataSource; import com.itheima.dao.BookDao; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;  import javax.sql.DataSource;  public class JdbcConfig {      @Bean     public DataSource dataSource(BookDao bookDao){         // 我们只需要调用即可,系统会为我们自动装配         System.out.println(bookDao);     }      }
  引入类型注入只需要为bean定义方法设置形参即可,容器会根据类型自动装配对象
  原文链接:https://www.cnblogs.com/qiuluoyuweiliang/p/16750470.html

吃维生素伤不伤肝呢?医生这4种维生素不建议长期吃维生素对于人体来说是非常重要的,担当着促进器官和组织运转的重要作用,如果体内缺乏维生素,身体会变的滞涩且不适,甚至会增加各种疾病的风险。随着现代医学的发展,很多维生素都可以进行专门冬日鹳影丨东方白鹳优雅的鸟界国宝央广网都昌12月16日消息(记者邓玉玲)时至候鸟越冬季。近日,大批国家一级保护动物东方白鹳在江西鄱阳湖都昌矶山附近水域湿地栖息觅食,与金色的晨曦波光粼粼的水面构成了一幅生态画卷。东第二届中国(玉溪)品质生活论坛嘉宾到我市参观考察12月14日至15日,参加第二届中国(玉溪)品质生活论坛的嘉宾一行对我市部分科创互联网项目及相关企业进行参观考察。考察组一行先后来到研和物流园区云南玉溪高原体育运动中心场馆玉溪市规陇上江南官鹅沟秋意陶然飒飒素秋,跨过西北荒凉的艽野广漠,在陇南的大山深处,隐逸着一条叫官鹅沟的大峡谷沟,沟内秋色令人赫然惊艳,与大西北满眼黄土梁峁的景象形成巨大的反差。陇上江南官鹅沟秋意陶然别有洞天秋入来峨眉,开启一场奇妙的研学之旅!乐游嘉学乐娃心体验读万卷书不如行万里路乐娃带你到乐山研学啦多的是你未曾触及过的世界今天乐娃带你线上游览峨眉山景区峨眉山博物馆峨眉山景区峨眉山高,山上山下几重天。闻名世界的峨眉山海拔美国核聚变取得突破,中国核聚变研究完全有可能率先实现商业化美国能源部宣布,美国的科学家首次在核聚变反应中产生净能量增益,这则新闻刚一出现,立刻在国内公共舆论场上激起了热议,公众的反应大致表现为两个方面一感到惊讶和错愕,表示难以置信。因为近年底新机潮来临,8天发布6款,换机不着急!进入2022第四季度,随着高通骁龙8Gen2处理器的发布,各大手机厂商都纷纷推出新机,一时间手机市场群魔乱舞,勾起了很多人的换机欲望。目前,vivo小米moto都发布了骁龙8Gen互联网医疗迎来短暂的春天随着疫情放开,连花清瘟等药物价格疯涨,且一药难求。而正当人们苦心求索时,一些互联网医疗巨头纷纷响应。京东健康承诺连花清瘟不涨价,并多备了一亿盒抗疫药阿里健康也表明,不仅原价供应该药八维云计算专业值得学吗?云,是继互联网变革之后的第三次IT大潮。上云已经逐渐成为企业发展的一种趋势和思维,凭借着在业务方面的敏捷性可拓展性效率性以及成本节约优势,云计算已然成为各行业企业智能化数字化转型升辛苦了!超千名快递员支援北京!近日有不少网友表示北京出现快递积压自己的快递在中转站几天都不动对此,国家邮政局就保障首都邮政快递业末端畅通工作对北京市邮政管理局和各快递企业总部进行调度。北京市邮政管理局明确两天内王卫点赞友商?北京快递保卫战,顺丰彰显大格局大气度当下,随着全面放开,国内新冠疫情到了另一个严峻的拐点时刻,特别是北京,正日益逼近感染高峰期。作为社会生活的毛细血管,快递物流企业们在当下的新冠疫情大背景下上演了一幕幕的鲜活的画面,
CBA三消息广东弃用三名球员,上海双外未注册,孙铭徽稳定两双大家好呀,我是北柠,各位小伙伴们要养成先赞后看的习惯哦!这个赛季的广东队目标依旧是冲击总冠军,他们在休赛期的时候进行了一点的球员阵容调整,广东队将周鹏给交易去了深圳队打球,这对他们速战速决!中国金花再轰20,进4强冲第2冠,世界排名升5位昨晚,ITF特尔纳瓦W60女单14决赛结束焦点战,中国金花王欣瑜作为头号种子连战连捷,再轰20淘汰对手打进4强,距离新赛季第2冠还差2胜。王欣瑜是中国女网00后,今年在澳网实现大满还是逃不过伤病!二当家出战14分钟伤退,约基奇摊上两大玻璃人?伤病这个问题是所有球员都不愿意碰到的,但是对于球队来讲,拿到大合同的球员们受伤,也非常影响球队的争冠进程,特别是对于两连MVP的约基奇来讲,如今正是他巅峰期出成绩的时候。如今NBA崩拳的真传以身为拳古人习艺,到底为什么?当健身操玩?自己骗自己?显然不是。往大的说,是为了上阵杀敌。往小的说,是与恶劣的自然环境做斗争。不要怀疑中华武艺。也不要神化了。聊一聊,以身为拳。滑个溜冰鞋去扬马归来备受跑友关注的世界田联金标赛事扬州鉴真半程马拉松赛(以下简称扬马)因新冠肺炎疫情影响自2020年按下暂停键后拟于今年11月13日重启和以往的赛事相比,2022年度扬马在比赛线路赛事又排名第一!抱歉库里詹姆斯杜兰特!联盟第一人是他的了近些年来詹姆斯库里杜兰特被视为联盟最强的三位球员,拿上赛季来说,杜兰特在赛季开打前被多个媒体评为联盟第一人,詹姆斯库里也高居最前列。不过新赛季的排名出现了很大变动。有一个球员的排名10。7日女排世锦赛东道主荷兰脆败出局,巴西日本反超中国2022女排世锦赛进入到第二阶段第三轮的比拼中,在率先进行的机场比赛中,并没有发生前两轮的诸多意外,东道主荷兰队即使坐拥主场之利,也没能从巴西手中拿到一局。E组日本30波多黎各意大李盈莹低迷仅8分,中国女排0比3不敌意大利,遭世锦赛第二场失利北京时间10月8日消息,2022年世界女排锦标赛第二阶段复赛继续进行,中国女排以0比3输给意大利队,遭遇开赛以来的第二场失利,本场比赛,李盈莹状态低迷只拿到8分,而意大利队埃格努2散文被赋了黄码以后有一个新词叫做时空伴随。有一种新状态叫做静默管理。有一种生活方式叫做居家隔离。国庆节提前收假,下班回家途中,途径某场所周边,并做逗留,不知不觉中已被赋了黄码。报备居家等待核酸检测。一封图书馆的情书我收到过一封邂逅的情书。情书上有这样看起来普通的句子很经常在图书馆里,不同的位置上都碰见过你。我从不对哪个位子宣示主权,喜欢兜兜转转找位子,可即便如此,我依然屡屡碰见你。你的样子实有两种关系,容易发展成情人问世间情为何物,直教人生死相许。在大千世界之中,虽然有很多令人向往的事物,但是唯有情关难过。毕竟它是源自于内心深处,是一种心灵上的慰藉,也是跳脱世间烦扰的好方法。然而,有些感情能够