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

一篇文章带你掌握主流基础框架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

31!张本智和打疯了,独拿2分,握拳怒吼庆祝,刘国梁小心成都世乒赛团体赛迎来一场焦点战,日本队和匈牙利队狭路相逢,张本智和先是31的比分战胜了亚当,然后在第四场比赛,张本智和再度登场,对阵塔马斯,日本主力以30的比分赢球,独自拿到2分,18岁奥运冠军管晨辰被保送浙江大学,如今身材发福,被网友调侃我们都在为梦前行,只是方式不同方向不一高考作为国内最公平的考试,难度自然不用多说,寒窗苦读十余载,取得高分被知名大学录取,若成绩一般或比较差,只能选择其他的院校,毕竟名校屈指可数。这就是轻功吧?太帅了最近,一段中国消防员飞速爬楼的视频火了视频中,消防员如离弦之箭瞬间抵达四楼这一幕令网友纷纷惊呼太帅了!近日,第十七届世界消防救援锦标赛在乌兹别克斯坦撒马尔罕开幕视频中正在举行的是攀土超赛程锡瓦斯VS哈塔斯堡,新闻排名积分榜队伍锡瓦斯VS哈塔斯堡联赛类型土超GBSPORS锡瓦斯体育曾经在土耳其联赛杯拿过一座冠军,2122赛季的土超联赛当中前一轮对上开塞利体育足球俱乐部以21让当时在客场的球队输掉比赛,斯波奥拉迪波没参加队内对抗赛,阿德巴约扩大了射程热火主教练埃里克斯波尔斯特拉接受媒体采访,谈到了热火球员维克托奥拉迪波。奥拉迪波今天没有参加球队的分组对抗,这并不是因为伤病的原因。斯波尔斯特拉在采访中表示。他现在的感觉很棒。我们邱党与杜达齐建功,德国男团与法国男团小组出线,印度队被淘汰团体世乒赛德国男团对战乌兹别克斯坦男团,最终德国男团30大胜对手。德国队第一个出战的还是邱党,对战的是乌兹别克斯坦队的舒克鲁克,最终邱党30击败对手。双方第一局的比赛邱党一开始正手维阿AC米兰生涯9大经典瞬间千里走单骑动图!顺祝56周岁生日快乐维阿AC米兰生涯9大经典瞬间千里走单骑动图!顺祝总统先生56周岁生日快乐本该是10月1日发的文字,因为太忙,拖到了今天!19951996赛季开始前,上赛季丢掉意甲冠军让贝卢斯科尼连越秀山今晚上演广东德比广州日报全媒体记者张喆今明两天,中超第21轮将全面开火。其中,广州城今晚将在越秀山与深圳队上演广东德比。明天,广州队远赴客场对阵长春亚泰,梅州客家则在主场迎战卫冕冠军山东泰山。广州姚明女篮成绩是惊喜,但不能头脑发热中国女篮获得世界杯亚军后,作为领队随队出征的中国篮协主席姚明接受新华社记者专访时表示,取得佳绩是这支队伍近10年来积累的结果,惊喜过后还是要冷静科学地总结分析,拿出框架计划,推动女下午1点!央视曝出争议猛料中国女排收坏消息,球迷吐槽声一片北京时间10月4日下午1点,针对中国女排的最新情况,央视评论员杨岭进行了爆料,他表示中国女排对阵巴西女排的比赛,王梦洁缺阵是因为存在发烧问题,而这样的情况也引发了很大的争议。杨岭这个人获奖80万,扣除费用,李梦到手数字曝光,落选的杨舒予也有奖女篮世界杯结束了,这绝对是值得中国篮球铭记的一届世界杯,在这届世界杯上,中国女篮时隔14年重回世界大赛的四强,时隔28年再一次进入女篮世界杯的四强,并且最终一举拿到了女篮世界杯的亚
TCL雷鸟鹏6se真香系列家里电视黑屏了,妈妈一直让我看看买台新的,端午看了下电视都好贵,想着618可能有优惠就又等了等,果然被我蹲到啦!55寸1400到手一台带运动补偿智能语音还是4K超高清的电视,简直太每逢北京国安,上海上港的比赛为何总是有争议呢深圳球迷问,为何徐新只停赛一场,四川球迷问,为何北京国安球员的手球,裁判选择无视呢?话说北京国安和上海上港的比赛结束后,很多球迷都说北京国安,上海上港遇到有争议的判罚总是受益的一方毛雪汪第二期热播海信空调成美食场景主角6月27日毛雪汪夏季番第二期准时上线。这期节目国民组合凤凰传奇惊喜登场,二人竟反客为主与毛不易李雪琴一起制作美食热聊八卦,把一个聊天综艺变成了美食番,为毛雪汪的粉丝奉献上一份传奇盛七月你好!今天是个伟大日子!广西旅游年卡ampampamp张眼看广西祖国在我心中苏喆灯火通明不夜天,举世瞩目交政权。收复失地洗耻辱,国歌铿锵奏凯旋。五星红旗扬正气,东方之珠我家园。三军英姿立威武,华夏千古笑开颜。今天是个伟大的日子建党101周年,香老年人缺钙危害大!日常做好这4件事,不用为缺钙发愁老年人最怕的就是缺钙,因为骨头主要组成部分是钙质,那些饮食均衡营养适当去晒太阳运动量充足的人,钙质获取和吸收不成问题。而在骨头健康的情况下可以远离骨质疏松症,然而,有不少老年人容易痛风20多年多处痛风石,难治性痛风,一方苗药痛风停,尿酸降300开门见山,今天分享一个难治性痛风的中药调理的非常病例。男性患者50岁,20多年前就不知道什么原因左脚第一跖趾关节开始肿痛,同时伴有关节肿胀关节功能受损活动异常。当时关节周围皮肤红,清热解暑这些凉茶不推荐多喝,中医推荐四种饮品最近,全国不分南北逐渐高温,消暑解渴的需求也就来了。今天就来介绍一下常见的消暑饮品。为什么要喝解暑饮品,水不行么?人体的主要排水方式有两种排尿流汗。一般来说,人体每天的水分排出量在传统医学话你知支气管炎(咳嗽),风寒袭肺怎么治?急性气管支气管炎是由生物理化刺激或过敏等因素引起的急性气管支气管黏膜炎症。多散发,无流行倾向,年老体弱者易感。症状主要为咳嗽和咳痰,常发生于寒冷季节或气候突变时,也可由急性上呼吸道功勋队长将重返武汉队首发,曾是当红国脚,却差点被李金羽用废武汉队在新赛季中超属于高开低走,球队前期踢得不错,取得了三连胜的战绩。这让很多球迷都觉得武汉队要换种活法了,结果他们高兴早了。武汉队在随后比赛中就连战连败,让主帅李金羽深陷下课危机欧文谈女儿参加真人秀一开始很难接受但她开心就好北京时间7月2日消息,欧文女儿杰玛(GemmaOwen)正在参加真人秀节目LoveIsland,欧文接受CheshireLive采访时谈到了对此的看法。对于女儿参加真人秀节目,欧文血拼防守周琦艾伦发威男篮世预赛惜败澳大利亚这场球如果单看上半场,大导我都想给顾全磕一个,虽慢且准!无愧底角最稳定的男人,两个强投让人大呼过瘾。而另一个不得不说的是周琦又变强了,他的攻防依旧是中国队独一档的存在。其实当澳大利