1_Spring_概念介绍_了解
Spring是分层的全栈式的轻量级开发框架,以IOC和AOP为核心,官网是https://spring.io
Spring优势
1 方便解耦,简化开发
Spring通过容器,将对象的创建从代码中剥离出来,交给Spring控制,避免直接编码造成模块之间的耦合度高,用户也不必自己编码处理对象的单例和多例控制,主要关注接口功能即可,不用关注具体使用哪个实现类和实现细节问题
2 AOP切面编程
AOP切面编程是程序设计的一种概念,Spring对该概念实现的比较好,通过切面编程我们可以在不修改原有代码的情况下实现功能的增加,通常用于 事务控制,日志记录,性能检测,权限控制等等
3 声明式事务
事务的控制可以托管给Spring,我们通过注解或者配置文件声明事务的处理方式即可,不用我们自己去编码处理
4 整合JUNIT,方便测试
spring整合JUNIT单元测试,对于项目的功能都可以进行轻松快速的测试,便于我们调试程序
5方便整合各种优秀的框架
SSM> Spring+SpringMVC +MyBatis
SSH> Spring+Hibernate +Strust
6 丰富的功能封装
spring对JAVAEE(JDBC ,JAVAMail,)都进行了一系列的封装,简化我们对于API的使用,提高程序的开发效率
7 规范的源码学习样本
spring的源码设计巧妙,结构清晰,大量使用了设计模式,是java代码规范编写的典范,也是高级程序员面试中经常会问到的源码
Spring的体系结构
1. Data Access/Integration(数据访问/集成)
数据访问/集成层包括 JDBC、ORM、OXM、JMS 和 Transactions 模块,具体介绍如下。
- JDBC 模块:提供了一个 JDBC 的抽象层,大幅度减少了在开发过程中对数据库操作的编码。
- ORM 模块:对流行的对象关系映射 API,包括 JPA、JDO、Hibernate和 iBatis 提供了的集成层。
- OXM 模块:提供了一个支持对象/XML 映射的抽象层实现,如 JAXB、Castor、XMLBeans、JiBX 和 XStream。
- JMS 模块:指 Java消息服务,包含的功能为生产和消费的信息。
- Transactions 事务模块:支持编程和声明式事务管理实现特殊接口类,并为所有的 POJO。
2. Web 模块
Spring 的 Web 层包括 Web、Servlet、Struts 和 Portlet 组件,具体介绍如下。
- Web 模块:提供了基本的 Web 开发集成特性,例如多文件上传功能、使用的 Servlet 监听器的 IoC 容器初始化以及 Web 应用上下文。
- Servlet模块:包括 Spring 模型—视图—控制器(MVC)实现 Web 应用程序。
- Struts 模块:包含支持类内的 Spring 应用程序,集成了经典的 Struts Web 层。
- Portlet 模块:提供了在 Portlet 环境中使用 MV C实现,类似 Web-Servlet 模块的功能。
3. Core Container(核心容器)
Spring 的核心容器是其他模块建立的基础,由 Beans 模块、Core 核心模块、Context 上下文模块和 Expression Language 表达式语言模块组成,具体介绍如下。
- Beans 模块:提供了 BeanFactory,是工厂模式的经典实现,Spring 将管理对象称为 Bean。
- Core 核心模块:提供了 Spring 框架的基本组成部分,包括 IoC 和 DI 功能。
- Context 上下文模块:建立在核心和 Beans 模块的基础之上,它是访问定义和配置任何对象的媒介。ApplicationContext 接口是上下文模块的焦点。
- Expression Language 模块:是运行时查询和操作对象图的强大的表达式语言。
4. 其他模块
Spring的其他模块还有 AOP、Aspects、Instrumentation 以及 Test 模块,具体介绍如下。
- AOP 模块:提供了面向切面编程实现,允许定义方法拦截器和切入点,将代码按照功能进行分离,以降低耦合性。
- Aspects 模块:提供与 AspectJ 的集成,是一个功能强大且成熟的面向切面编程(AOP)框架。
- Instrumentation 模块:提供了类工具的支持和类加载器的实现,可以在特定的应用服务器中使用。
- Test 模块:支持 Spring 组件,使用 JUnit 或 TestNG 框架的测试。
2_Spring_IOC概念引入_重要
简单的说就是,创建对象的权利,或者是控制的位置,由JAVA代码转移到spring容器,由spring的容器控制对象的创建,就是控制反转,spring创建对象时,会读取配置文件中的信息,然后使用反射给我们创建好对象之后在容器中存储起来,当我们需要某个对象时,通过id获取对象即可,不需要我们自己去new.
一句话:创建对象交给容器
Spring解耦合的原理
创建maven项目,设置maven
先创建一个空项目
名字可以是spring_all
在项目下创建模块 名字可以是spring_test_01
pom.xml中导入spring依赖
- <dependencies>
- <dependency>
- <groupId>springframework</groupId>
- <artifactId>spring-core</artifactId>
- <version>3.5</version>
- </dependency>
- <dependency>
- <groupId>springframework</groupId>
- <artifactId>spring-beans</artifactId>
- <version>3.5</version>
- </dependency>
- <dependency>
- <groupId>springframework</groupId>
- <artifactId>spring-context</artifactId>
- <version>3.5</version>
- </dependency>
- <dependency>
- <groupId>springframework</groupId>
- <artifactId>spring-expression</artifactId>
- <version>3.5</version>
- </dependency>
- </dependencies>
四个依赖介绍
spring-context 上下文,容器
spring-beans 创建对象
spring-core 核心jar
spring-expression 表达式jar
但是事实上,我们导入spring-context的时候,会自动导入其他依赖的jar,自动进行了依赖传递
所以,导入一个spring-context 依赖也可以
依赖传递关系图如下
为了方便测试,我们导入Junit测试依赖
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>13.1</version>
- <scope>test</scope>
- </dependency>
在项目中定义一个接口和实现类
EmpDao接口和实现类
接口中定义一个方法并在实现类中实现
接口
实现类
在spring配置容器中的对象
创建spring配置文件
文件名没有明确要求,暂时可以叫spring
在spring.xml中配置一个需要由容器初始化的对象
测试通过容器获取对象
3_Spring_IOC原理分析_重要
IOC底层原理
1 XML解析技术读取配置文件
- <bean id=”empDao”class=”com.msb.dao.impl.EmpDaoImpl”></bean>
将上面的信息读取进入程序 对象的ID ,一个是对象的类的全路径名
2 反射技术实例化对象,放到容器中
获得类的字节码
Class clazz =Class.forName(“com.msb.dao.impl.EmpDaoImpl”)
通过字节码实例化对象
Object obj = clazz.newInstance();
将对象放到一个map集合中
map.put(“empDao”,obj)
3工厂模式返回Bean对象 getBean方法
public Object getBean(String name){
Object obj =map.get(name);
return obj;
}
IOC接口
BeanFactory 接口: IOC容器基本功能接口,是spring内部使用的接口,我们在处理业务时一般不直接使用该接口
ApplicationContext 接口: BeanFactory的子接口,提供更多更强大的功能,研发人员一般使用的接口
4_Spring_XML方式实现DI
spring中的Bean的管理:
Bean(汉译咖啡豆). 又称JAVABean.其实就是JAVA程序程序中的一个个对象,所以Bean的管理其实就是spring对于JAVA程序中的对象的管理
管理的内容是什么
1 对象的创建 IOC
IOC 叫做控制反转,就是Spring给我们创建对象,然后我们直接用,不用自己NEW,前面已经解释过
IOC处理的是对象如何创建的问题
2 属性的赋值 DI
DI Dependency Injection,即“依赖注入” 就是创建属性时给对象属性赋值
对象功能的实现往往要依赖属性的值,那么给对象属性赋值就可以说成是依赖注入
由于对象属性不仅仅是基本数据类型,还可能是其他类,或者引用类型
那么依赖注入将会把更多的对象之间的关系整理到一起,可以行程一个庞大的依赖关系
DI处理的是对象的属性赋值和互相依赖的关系
spring给我们提供了两种关于bean的方式
1 基于XML方式的Bean管理
2 基于注解方式的Bean管理
创建新的模块并导入以下依赖
依赖
- <dependency>
- <groupId>springframework</groupId>
- <artifactId>spring-context</artifactId>
- <version>3.5</version>
- </dependency>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>13.1</version>
- <scope>test</scope>
- </dependency>
创建spring配置文件,一般spring的配置文件很多人约定俗称为application****.xml
准备一个要实例化的类
- publicclass User {
- private Integer userid;
- private String username;
- private String password;
- @Override
- public String toString() {
- return “User{” +
- “userid=” + userid +
- “, username='” + username + ‘\” +
- “, password='” + password + ‘\” +
- ‘}’;
- }
- public User() {
- out.println(“noArgConstructor”);
- }
- public User(Integer userid, String username, String password) {
- out.println(“allArgConstructor”);
- this.userid = userid;
- this.username = username;
- this.password = password;
- }
- public void setUserid(Integer userid) {
- out.println(“setUserid”);
- this.userid = userid;
- }
- public void setUsername(String username) {
- out.println(“setUsername”);
- this.username = username;
- }
- public void setPassword(String password) {
- out.println(“setpassword”);
- this.password = password;
- }
- }
IOC创建对象
通过无参构造方法构造对象
- <bean id=”user1″class=”com.msb.bean.User”></bean>
<bean> 标签的常见属性
- <bean id=”user1″class=”com.msb.bean.User” name=”user1″ scope=”prototype” lazy-init=”true” ></bean>
id 对象的id
class 类的全路径名
name 和id类似,一般不用
scope 控制对象单例多例和使用范围
singleton作用域(scope 默认值), Spring IOC容器中只会存在一个共享的bean实例
prototype作用域部署的bean,每一次获取都会产生一个新的bean实例,相当与一个new的操作
request表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP request内有效
session作用域表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP session内有效
global session作用域类似于标准的HTTP Session作用域,不过它仅仅在基于portlet的web应用中才有意义
lazy-init 懒加载 调用getBean的时候再去实例化对象
DI给对象属性赋值
1 通过set方法给对象属性赋值
- <!–property 就是在使用set方法实现依赖注入–>
- <bean id=”user1″ class=”com.msb.bean.User”>
- <property name=”userid” value=”1″></property>
- <property name=”username” value=”张三”></property>
- <property name=”password” value=”abcdefg”></property>
- </bean>
2 通过有参构造给对象属性赋值
- <!–
- constructor-arg 就是在使用构造方法实现依赖注入
- constructor-arg 的个数必须和某个构造方法的参数个数向对应
- name指的是参数名
- index指的是参数的索引
- value指的是参数值
- –>
- <bean id=”user2″ class=”com.msb.bean.User”>
- <constructor-arg name=”userid” value=”2″></constructor-arg>
- <constructor-arg name=”username” value=”小明”></constructor-arg>
- <constructor-arg name=”password” value=”123456789″></constructor-arg>
- </bean>
- <bean id=”user3″ class=”com.msb.bean.User”>
- <constructor-arg index=”0″ value=”3″></constructor-arg>
- <constructor-arg index=”1″ value=”小黑”></constructor-arg>
- <constructor-arg index=”2″ value=”987654321″></constructor-arg>
- </bean>
3 通过p名称空间和c名称空间给对象属性赋值
添加约束
- <?xml version=”1.0″encoding=”UTF-8″?>
- <beans xmlns=”http://www.springframework.org/schema/beans”
- xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
- xmlns:p=”http://www.springframework.org/schema/p”
- xmlns:c=”http://www.springframework.org/schema/c”
- xsi:schemaLocation=”http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans.xsd”>
配置对象
- <!–p名称空间,就是对property的简化处理–>
- <bean id=”user4″ class=”com.msb.bean.User” p:userid=”4″ p:username=”小东” p:password=”111111″ ></bean>
- <!–c名称空间,就是对constructor-arg的简化–>
- <bean id=”user5″ class=”com.msb.bean.User” c:userid=”5″ c:username=”小西” c:password=”222222″ ></bean>
测试代码
- public class Test1 {
- @Test
- public void testGetBean(){
- ApplicationContext context =new ClassPathXmlApplicationContext(“applicationContext.xml”);
- User user1 = context.getBean(“user1”, User.class);
- User user2 = context.getBean(“user2”, User.class);
- User user3 = context.getBean(“user3”, User.class);
- User user4 = context.getBean(“user4”, User.class);
- User user5 = context.getBean(“user5”, User.class);
- out.println(user1);
- out.println(user2);
- out.println(user3);
- out.println(user4);
- out.println(user5);
- }
- }
4 注入空值和特殊符号
- <bean id=”user1″ class=”com.msb.bean.User”>
- <!–null值–>
- <property name=”userid”>
- <null></null>
- </property>
- <!–特殊符号 转译字符 < < >> & & –>
- <property name=”username” value=”&xiaoming<>”></property>
- <!– 特殊符号 <![CDATA[内容]]> –>
- <property name=”password”>
- <value><![CDATA[&<123456>]]></value>
- </property>
- </bean>
5 关于bean引用
实体类
- packagemsb.bean;
- importutil.Date;
- /**
- * @Author: Ma HaiYang
- * @Description: MircoMessage:Mark_7001
- */
- publicclass Mouse {
- private String name;
- private Date birthdate;
- @Override
- public String toString() {
- return “Mouse{” +
- “name='” + name + ‘\” +
- “, birthdate=” + birthdate +
- ‘}’;
- }
- public Mouse() {
- }
- public Mouse(String name, Date birthdate) {
- this.name = name;
- this.birthdate = birthdate;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public Date getBirthdate() {
- return birthdate;
- }
- public void setBirthdate(Date birthdate) {
- this.birthdate = birthdate;
- }
- }
- packagemsb.bean;
- /**
- * @Author: Ma HaiYang
- * @Description: MircoMessage:Mark_7001
- */
- publicclass Cat {
- private String name;
- private Mouse mouse1;
- @Override
- public String toString() {
- return “Cat{” +
- “name='” + name + ‘\” +
- “, mouse1=” + mouse1 +
- ‘}’;
- }
- public Cat() {
- }
- public Cat(String name, Mouse mouse1) {
- this.name = name;
- this.mouse1 = mouse1;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public Mouse getMouse1() {
- return mouse1;
- }
- public void setMouse1(Mouse mouse1) {
- this.mouse1 = mouse1;
- }
- }
xml 配置
- <!–告诉容器准备一个Date对象–>
- <bean id=”date1″ class=”java.util.Date”></bean>
- <bean id=”mouse1″ class=”com.msb.bean.Mouse”>
- <property name=”name” value=”Jerry”></property>
- <!–bean引用引用外部bean–>
- <property name=”birthdate” ref=”date1″></property>
- </bean>
- <bean id=”cat1″ class=”com.msb.bean.Cat”>
- <property name=”name” value=”Tom”></property>
- <!–引用内部bean–>
- <property name=”mouse1″ >
- <bean class=”com.msb.bean.Mouse”>
- <property name=”name” value=”Jerry2″></property>
- <property name=”birthdate”>
- <bean class=”java.util.Date”></bean>
- </property>
- </bean>
- </property>
- </bean>
- <bean id=”mouse2″ class=”com.msb.bean.Mouse”></bean>
- <bean id=”cat2″ class=”com.msb.bean.Cat”>
- <property name=”name” value=”Tom2″></property>
- <!–级联引入bean–>
- <property name=”mouse1″ ref=”mouse2″></property>
- <!–用反射调用get*** 方法,获得对象之后,再赋值–>
- <property name=”mouse1.name” value=”Jerry3″></property>
- <property name=”mouse1.birthdate”>
- <bean class=”java.util.Date”></bean>
- </property>
- </bean>
6 关于集合注入
实体类
- packagemsb.bean;
- /**
- * @Author: Ma HaiYang
- * @Description: MircoMessage:Mark_7001
- */
- publicclass Book {
- private String bname;
- private String author;
- @Override
- public String toString() {
- return “Book{” +
- “bname='” + bname + ‘\” +
- “, author='” + author + ‘\” +
- ‘}’;
- }
- public Book() {
- }
- public Book(String bname, String author) {
- this.bname = bname;
- this.author = author;
- }
- public String getBname() {
- return bname;
- }
- public void setBname(String bname) {
- this.bname = bname;
- }
- public String getAuthor() {
- return author;
- }
- public void setAuthor(String author) {
- this.author = author;
- }
- }
- packagemsb.bean;
- importutil.Arrays;
- importutil.List;
- importutil.Map;
- importutil.Set;
- /**
- * @Author: Ma HaiYang
- * @Description: MircoMessage:Mark_7001
- */
- publicclass Student {
- private String[] books;
- private Set<String> bookSet;
- private List<String> bookList;
- private Map<String,String> bookMap;
- private List<Book> bookList2;
- @Override
- public String toString() {
- return “Student{” +
- “books=” + Arrays.toString(books) +
- “, bookSet=” + bookSet +
- “, bookList=” + bookList +
- “, bookMap=” + bookMap +
- “, bookList2=” + bookList2 +
- ‘}’;
- }
- public String[] getBooks() {
- return books;
- }
- public void setBooks(String[] books) {
- this.books = books;
- }
- public Set<String> getBookSet() {
- return bookSet;
- }
- public void setBookSet(Set<String> bookSet) {
- this.bookSet = bookSet;
- }
- public List<String> getBookList() {
- return bookList;
- }
- public void setBookList(List<String> bookList) {
- this.bookList = bookList;
- }
- public Map<String, String> getBookMap() {
- return bookMap;
- }
- public void setBookMap(Map<String, String> bookMap) {
- this.bookMap = bookMap;
- }
- public List<Book> getBookList2() {
- return bookList2;
- }
- public void setBookList2(List<Book> bookList2) {
- this.bookList2 = bookList2;
- }
- public Student() {
- }
- public Student(String[] books, Set<String> bookSet, List<String> bookList, Map<String, String> bookMap, List<Book> bookList2) {
- this.books = books;
- this.bookSet = bookSet;
- this.bookList = bookList;
- this.bookMap = bookMap;
- this.bookList2 = bookList2;
- }
- }
配置文件
- <?xml version=”1.0″encoding=”UTF-8″?>
- <beansxmlns=”http://www.springframework.org/schema/beans”
- xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
- xmlns:p=”http://www.springframework.org/schema/p”
- xmlns:c=”http://www.springframework.org/schema/c”
- xmlns:util=”http://www.springframework.org/schema/util”
- xsi:schemaLocation=”
- http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans.xsd
- http://www.springframework.org/schema/util
- http://www.springframework.org/schema/util/spring-util.xsd
- “>
- <!–定义公共集合–>
- <util:list id=”outerbookList”>
- <!–声明多个Book对象–>
- <bean id=”b1″ class=”com.msb.bean.Book” p:bname=”JAVA” p:author=”马士兵”></bean>
- <bean id=”b2″ class=”com.msb.bean.Book” p:bname=”Go” p:author=”马士兵”></bean>
- <bean id=”b3″ class=”com.msb.bean.Book” p:bname=”JVM” p:author=”马士兵”></bean>
- </util:list>
- <bean id=”student1″ class=”com.msb.bean.Student”>
- <!–数组属性注入–>
- <property name=”books”>
- <array>
- <value>JAVA</value>
- <value>MySQL</value>
- <value>Spring</value>
- </array>
- </property>
- <!–set集合注入–>
- <property name=”bookSet”>
- <set>
- <value>JAVA</value>
- <value>MySQL</value>
- <value>Spring</value>
- </set>
- </property>
- <!–list集合注入–>
- <property name=”bookList”>
- <list>
- <value>JAVA</value>
- <value>MySQL</value>
- <value>Spring</value>
- </list>
- </property>
- <!–map集合注入–>
- <property name=”bookMap”>
- <map>
- <entry key=”JAVA” value=”马士兵”></entry>
- <entry key=”Go” value=”马士兵”></entry>
- <entry key=”JVM” value=”马士兵”></entry>
- </map>
- </property>
- <!–List对象集合注入–>
- <property name=”bookList2″ ref=”outerbookList”></property>
- </bean>
- </beans>
7 工厂方式获取bean
特点 : bean标签中定义的class类不是返回的对象的类,而是生产该对象的工厂
工厂模式:GOF 设计模式
spring中给我们定义好了一个工厂接口,可以生产对象的接口,我们可以通过工厂来获取bean
定义工厂对象 实现 FactoryBean接口
- packagemsb.bean;
- importspringframework.beans.factory.FactoryBean;
- /**
- * @Author: Ma HaiYang
- * @Description: MircoMessage:Mark_7001
- */
- publicclass BookFactory implements FactoryBean<Book> {
- @Override
- public Book getObject() throws Exception {
- Book book=new Book();
- setBname(“JAVA”);
- setAuthor(“马士兵”);
- return book;
- }
- @Override
- public Class<?> getObjectType() {
- return null;
- }
- }
配置文件
- <bean id=”book”class=”msb.bean.BookFactory”></bean>
测试代码
- @Test
- public void testGetBean(){
- ApplicationContext applicationContext=new ClassPathXmlApplicationContext(“applicationContext5.xml”);
- Book book = applicationContext.getBean(“book”, class);
- out.println(book);
- }
5_Spring_Bean的生命周期
bean从创建到销毁经历的各个阶段以及每个阶段所调用的方法
1 通过构造器创建bean实例 执行构造器
2 为bean属性赋值 执行set方法
3 初始化bean 调用bean的初始化方法,需要配置指定调用的方法
4 bean的获取 容器对象 getBean方法
5 容器关闭销毁bean 调用销毁方法,需要配置指定调用的方法
测试生命周期
准备bean
- package com.msb.bean;
- /**
- * @Author: Ma HaiYang
- * @Description: MircoMessage:Mark_7001
- */
- publicclass User {
- private Integer userid;
- private String username;
- private String password;
- public void initUser(){
- out.println(“第三步:User初始化”);
- }
- public User() {
- out.println(“第一步:User构造”);
- }
- public void destoryUser(){
- out.println(“第五步:User销毁”);
- }
- @Override
- public String toString() {
- return “User{” +
- “userid=” + userid +
- “, username='” + username + ‘\” +
- “, password='” + password + ‘\” +
- ‘}’;
- }
- public User(Integer userid, String username, String password) {
- this.userid = userid;
- this.username = username;
- this.password = password;
- }
- public void setUserid(Integer userid) {
- out.println(“setUserid”);
- this.userid = userid;
- }
- public void setUsername(String username) {
- out.println(“第二步:User属性赋值”);
- this.username = username;
- }
- public void setPassword(String password) {
- this.password = password;
- }
- }
配置bean
- <?xml version=”1.0″encoding=”UTF-8″?>
- <beansxmlns=”http://www.springframework.org/schema/beans”
- xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
- xmlns:p=”http://www.springframework.org/schema/p”
- xmlns:c=”http://www.springframework.org/schema/c”
- xsi:schemaLocation=”http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans.xsd”>
- <bean id=”user” class=”com.msb.bean.User” init-method=”initUser” destroy-method=”destoryUser”>
- <property name=”username” value=”xiaoming”></property>
- </bean>
- </beans>
测试bean
- packagemsb.test;
- importmsb.bean.User;
- importjunit.Test;
- importspringframework.context.ApplicationContext;
- importspringframework.context.support.ClassPathXmlApplicationContext;
- /**
- * @Author: Ma HaiYang
- * @Description: MircoMessage:Mark_7001
- */
- publicclass Test1 {
- @Test
- public void testGetBean(){
- ClassPathXmlApplicationContext context =new ClassPathXmlApplicationContext(“applicationContext.xml”);
- User user = context.getBean(“user”,User.class);
- out.println(“第四步:User对象从容器中获取”);
- // 关闭容器
- close();
- }
- }
关于后置处理器
1 通过构造器创建bean实例 执行构造器
2 为bean属性赋值 执行set方法
3 把bean实例传递给bean的后置处理器的方法
4 初始化bean 调用bean的初始化方法,需要配置指定调用的方法
5 把bean实例传递给bean的后置处理器的方法
6 bean的获取 容器对象 getBean方法
7 容器关闭销毁bean 调用销毁方法,需要配置指定调用的方法
1 创建后置处理器 实现 BeanPostProcesser 重写两个方法
- packagemsb.beanProcesser;
- importspringframework.beans.BeansException;
- importspringframework.beans.factory.config.BeanPostProcessor;
- /**
- * @Author: Ma HaiYang
- * @Description: MircoMessage:Mark_7001
- */
- publicclass MyBeanProcesser implements BeanPostProcessor {
- @Override
- public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
- //Object bean 实例化的bean
- //String beanName bean的id
- out.println(“bean:初始化方法之前”);
- return bean;// 这里必须return bean
- }
- @Override
- public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
- out.println(“bean:初始化方法之后”);
- return bean;// 这里必须returnbean
- }
- }
2 配置后置处理器,对容器中的所有bean添加后置处理器的生命周期
- <?xml version=”1.0″encoding=”UTF-8″?>
- <beansxmlns=”http://www.springframework.org/schema/beans”
- xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
- xmlns:p=”http://www.springframework.org/schema/p”
- xmlns:c=”http://www.springframework.org/schema/c”
- xsi:schemaLocation=”http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans.xsd”>
- <bean id=”user” class=”com.msb.bean.User” init-method=”initUser” destroy-method=”destoryUser”>
- <property name=”username” value=”xiaoming”></property>
- </bean>
- <bean id=”myBeanProcesser” class=”com.msb.beanProcesser.MyBeanProcesser”></bean>
- </beans>
BeanPostProcessor接口作用:
如果我们想在Spring容器中完成bean实例化、配置以及其他初始化方法前后要添加一些自己逻辑处理。我们需要定义一个或多个BeanPostProcessor接口实现类,然后注册到Spring IoC容器中。
1、接口中的两个方法都要将传入的bean返回,而不能返回null,如果返回的是null那么我们通过getBean方法将得不到目标。
2、ApplicationContext会自动检测在配置文件中实现了BeanPostProcessor接口的所有bean,并把它们注册为后置处理器,然后在容器创建bean的适当时候调用它,因此部署一个后置处理器同部署其他的bean并没有什么区别。而使用BeanFactory实现的时候,bean 后置处理器必须通过代码显式地去注册,在IoC容器继承体系中的ConfigurableBeanFactory接口中定义了注册方法
6_Spring_Bean的自动装配
bean自动装配
通过property标签可以手动指定给属性进行注入
我们也可以通过自动转配,完成属性的自动注入,就是自动装配,可以简化DI的配置
准备实体类
- package com.msb.bean;
- /**
- * @Author: Ma HaiYang
- * @Description: MircoMessage:Mark_7001
- */
- publicclass Dept {
- }
- packagemsb.bean;
- /**
- * @Author: Ma HaiYang
- * @Description: MircoMessage:Mark_7001
- */
- publicclass Emp {
- private Dept dept;
- @Override
- public String toString() {
- return “Emp{” +
- “dept=” + dept +
- ‘}’;
- }
- public Dept getDept() {
- return dept;
- }
- public void setDept(Dept dept) {
- this.dept = dept;
- }
- public Emp() {
- }
- public Emp(Dept dept) {
- this.dept = dept;
- }
- }
配置文件
- <?xml version=”1.0″encoding=”UTF-8″?>
- <beansxmlns=”http://www.springframework.org/schema/beans”
- xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
- xmlns:p=”http://www.springframework.org/schema/p”
- xmlns:c=”http://www.springframework.org/schema/c”
- xsi:schemaLocation=”http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans.xsd”>
- <bean id=”dept” class=”com.msb.bean.Dept”></bean>
- <!–
- autowire 属性控制自动将容器中的对象注入到当前对象的属性上
- byName 根据目标id值和属性值注入,要保证当前对象的属性值和目标对象的id值一致
- byType 根据类型注入,要保证相同类型的目标对象在容器中只有一个实例
- –>
- <bean id=”emp” class=”com.msb.bean.Emp” autowire=”byName”></bean>
- </beans>
测试代码
- packagemsb.test;
- importmsb.bean.Emp;
- importmsb.bean.User;
- importjunit.Test;
- importspringframework.context.support.ClassPathXmlApplicationContext;
- /**
- * @Author: Ma HaiYang
- * @Description: MircoMessage:Mark_7001
- */
- publicclass Test2 {
- @Test
- public void testGetBean(){
- ClassPathXmlApplicationContext context =new ClassPathXmlApplicationContext(“applicationContext2.xml”);
- Emp emp = context.getBean(“emp”, Emp.class);
- out.println(emp);
- }
- }
7_Spring_使用外部属性配置文件
spring容器可以读取.properties属性配置文件,可以将文件中的信息注入给bean
例如,引入Druid数据源,配置连接池信息
1 导入Druid依赖和mysql-connector依赖
- <dependency>
- <groupId>alibaba</groupId>
- <artifactId>druid</artifactId>
- <version>1.10</version>
- </dependency>
- <dependency>
- <groupId>mysql</groupId>
- <artifactId>mysql-connector-java</artifactId>
- <version>0.22</version>
- </dependency>
2 准备属性配置文件
resources目录下准备一个jdbc.properties属性配置文件
配置文件内容
- jdbc_driver=com.mysql.cj.jdbc.Driver
- jdbc_url=jdbc:mysql://0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
- jdbc_username=root
- jdbc_password=root
applicationContext中添加context名称空间 并读取属性配置文件
配置druid数据源将属性配置文件中的信息注入到连接池中
- <?xml version=”1.0″encoding=”UTF-8″?>
- <beansxmlns=”http://www.springframework.org/schema/beans”
- xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
- xmlns:p=”http://www.springframework.org/schema/p”
- xmlns:c=”http://www.springframework.org/schema/c”
- xmlns:context=”http://www.springframework.org/schema/context”
- xsi:schemaLocation=”http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context.xsd
- “>
- <context:property-placeholder location=”classpath:jdbc.properties”/>
- <bean id=”dataSource” class=”com.alibaba.druid.pool.DruidDataSource”>
- <property name=”username” value=”${jdbc_username}”></property>
- <property name=”password” value=”${jdbc_password}”></property>
- <property name=”url” value=”${jdbc_url}”></property>
- <property name=”driverClassName” value=”${jdbc_driver}”></property>
- </bean>
- </beans>
3 DEBUG测试代码
8_Spring_注解方式管理bean
1注解方式创建对象IOC
导入依赖 aop
@Component 放在类上,用于标记,告诉spring当前类需要由容器实例化bean并放入容器中
该注解有三个子注解
@Controller 用于实例化controller层bean
@Service 用于实例化service层bean
@Repository 用于实例化持久层bean
当不确定是哪一层,就用Component
这几个注解互相混用其实也可以,但是不推荐
第一步:在applicationContext.xml中配置开启注解扫描
- <?xml version=”1.0″encoding=”UTF-8″?>
- <beansxmlns=”http://www.springframework.org/schema/beans”
- xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
- xmlns:p=”http://www.springframework.org/schema/p”
- xmlns:c=”http://www.springframework.org/schema/c”
- xmlns:context=”http://www.springframework.org/schema/context”
- xsi:schemaLocation=”http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context.xsd
- “>
- <!–添加注解扫描,扫描指定的包,将包中的所有有注解的类实例化
- base-package 后面放要扫描的包
- 如果有多个包需要扫描,可以使用逗号隔开 com.msb.bean,com.msb.service
- 或者可以写上一层包路径 msb
- 可以通过注解指定bean的id@Component(“user1”)
- 如果不指定,则id默认是 类名首字母小写
- –>
- <context:component-scan base-package=”com.msb.bean”></context:component-scan>
- </beans>
第二步:在类上添加注解,让spring容器给我们创建bean实例并存储于容器中
- packagecom.msb.bean;
- importorg.springframework.stereotype.Component;
- /**
- * @Author: Ma HaiYang
- * @Description: MircoMessage:Mark_7001
- */
- @Component(value= “user1”)
- public class User {
- }
测试代码
- packagemsb.test;
- importmsb.bean.User;
- importjunit.Test;
- importspringframework.context.ApplicationContext;
- importspringframework.context.support.ClassPathXmlApplicationContext;
- /**
- * @Author: Ma HaiYang
- * @Description: MircoMessage:Mark_7001
- */
- publicclass Test1 {
- @Test
- public void testGetBean(){
- ApplicationContext context =new ClassPathXmlApplicationContext(“applicationContext.xml”);
- User user = context.getBean(“user1”, User.class);
- out.println(user);
- }
- }
组件扫描配置注解识别
- <!–
- use-default-filters=”false”
- 默认值为true 代表使用默认的扫描过滤器
- 默认的扫描过滤器会识别并包含 @Component @Controller @Service @Repository 四个注解
- 不使用默认的filter,使用我们自己的filter
- –>
- <!–控制只扫描Controller注解–>
- <context:component-scan base-package=”com.msb” use-default-filters=”false”>
- <context:include-filter type=”annotation” expression=”org.springframework.stereotype.Controller”/>
- </context:component-scan>
- <!–控制不扫描Controller注解–>
- <context:component-scan base-package=”com.msb” use-default-filters=”true”>
- <context:exclude-filter type=”annotation” expression=”org.springframework.stereotype.Controller”/>
- </context:component-scan>
2注解方式依赖注入DI
@Autowired 根据属性数据类型自动装配
@Qualifier 根据属性名称注入依赖
@Resources 可以根据类型,也可以根据名称注入
@Value 注入普通数据类型(8+String)
项目结构如下
applicationContext.xml中配置包扫描和读取属性配置文件
Dao层
接口
实现类
让容器扫描 Service层,实例化对象
接口
实现类
- packagemsb.service.impl;
- importmsb.dao.UserDao;
- importmsb.service.UserService;
- importspringframework.beans.factory.annotation.Autowired;
- importspringframework.beans.factory.annotation.Qualifier;
- importspringframework.beans.factory.annotation.Value;
- importspringframework.stereotype.Service;
- importannotation.Resource;
- /**
- * @Author: Ma HaiYang
- * @Description: MircoMessage:Mark_7001
- */
- @Service
- publicclass UserServiceImpl implements UserService {
- /*
- *@Autowired
- * 根据类型到容器中去寻找对应的对象,找到后给当前属性赋值
- * 不需要依赖 set方法
- * 属性类型可以是接口,会自动匹配对应的实现类对象
- * @Autowired配合 @Qualifier,可以通过名称指定注入的对象
- *
- * @Resource 如果不配置name 那么就是根据类型注入
- * @Resource(name=”userDaoImplB”) 配置name,就是根据名称注入
- *
- *
- * @Resource 是JDK中javax包的注解
- * @Autowired 和 @Qualifier 是spring中的注解
- *
- * @Value 可以个普通属性赋值
- * @Value 可以使用${}这种表达式获取系统的变量值
- * 或者是.properties属性配置文件中的值
- *
- * */
- //@Autowired
- //@Qualifier(“userDaoImplA”)
- //@Qualifier(“userDaoImplB”)
- //private UserDao userDao ;
- @Resource(name=”userDaoImplB”)
- private UserDao userDao ;
- @Value(“${username}”)
- private String sname;
- @Value(“boy”)
- private String sgender;
- @Value(“${age}”)
- private Integer sage;
- @Override
- public void add() {
- out.println(“userServiceImpl add … … “);
- out.println(sname);
- out.println(sgender);
- out.println(sage);
- add();
- }
- }
测试代码
- packagemsb.test;
- importmsb.service.UserService;
- importjunit.Test;
- importspringframework.context.ApplicationContext;
- importspringframework.context.support.ClassPathXmlApplicationContext;
- /**
- * @Author: Ma HaiYang
- * @Description: MircoMessage:Mark_7001
- */
- publicclass Test1 {
- @Test
- public void testGetBean(){
- ApplicationContext context =new ClassPathXmlApplicationContext(“applicationContext.xml”);
- UserService userService = context.getBean(“userServiceImpl”, UserService.class);
- add();
- }
- }
3完全使用注解(了解)
创建配置类,替代XML配置文件
测试代码
- @Test
- public void testGetBean2(){
- ApplicationContext context=new AnnotationConfigApplicationContext(SpringConfig.class);
- UserServiceImpl userService = context.getBean(“userServiceImpl”, UserServiceImpl.class);
- add();
- }