目录
IOC概念和原理
?编辑?Spring提供IOC容器实现的两种方式(两个接口)
IOC操作Bean管理
1.什么是Bean管理
2.IOC基于xml操作Bean管理
1、基于xml方式创建对象
?2、基于xml方式注入属性-使用set方法进行注入
3.基于xml方式注入属性-使用有参数构造
4、IOC操作Bean管理xml注入其他类型属性
4.基于xml方式注入属性-外部注入bean方式注入属性
5.基于xml方式注入属性-内部bean和级联赋值注入属性的方法
6.xml注入集合属性
7.工厂bean-FactoryBean?
?8.bean创建单例和多利
8.、bean生命周期
9.Bean的后置处理器?
10.xml自动装配
11.? ? ?IOC操作Bean管理(外部属性文件-数据库)
?基于注解方式操作bean管理
? ? ?1、什么是注解
? ? 2.Spring针对Bean管理中创建对象提供注解
?编辑3、基于注解方式实现对象创建
4、基于注解方式实现属性注入
5、基于注解方式实现属性注入
完全注解开发(了解SpringBoot会真正涉及)
Spring框架概述
1.Spring是轻量级的开源的JavaEE框架
2.Spring可以解决企业应用开发的复杂性
3.Spring有两个核心部分
? ? ? ? IOC:控制反转,把创建对象过程交给Spring进行管理
? ? ? ? Aop:面向切片,不修改源代码进行功能增强
4.Spring特点
? ? ? ? 方便解耦,简化开发
? ? ? ? Aop编程支持
? ? ? ? 方便程序测试
? ? ? ? 方便和替他框架进行整合
? ? ? ? 方便进行实务操作
? ? ? ? 降低API开发难度
5.使用到的jar包
IOC概念和原理
1.什么是IOC
- 控制反转,把对象创建和对象之间的调用过程,交给Spring管理
???????????在传统的 Java 应用中,一个类想要调用另一个类中的属性或方法,通常会先在其代码中通过 new Object() 的方式将后者的对象创建出来,然后才能实现属性或方法的调用。为了方便理解和描述,我们可以将前者称为“调用者”,将后者称为“被调用者”。也就是说,调用者掌握着被调用者对象创建的控制权。
但在 Spring 应用中,Java 对象创建的控制权是掌握在 IoC 容器手里的,其大致步骤如下。
- 开发人员通过 XML 配置文件、注解、Java 配置类等方式,对?Java 对象进行定义,例如在 XML 配置文件中使用 <bean> 标签、在 Java 类上使用 @Component 注解等。
- Spring 启动时,IoC 容器会自动根据对象定义,将这些对象创建并管理起来。这些被 IoC 容器创建并管理的对象被称为 Spring Bean。
- 当我们想要使用某个 Bean 时,可以直接从 IoC 容器中获取(例如通过 ApplicationContext 的 getBean() 方法),而不需要手动通过代码(例如 new Obejct() 的方式)创建。
IoC 带来的最大改变不是代码层面的,而是从思想层面上发生了“主从换位”的改变。原本调用者是主动的一方,它想要使用什么资源就会主动出击,自己创建;但在 Spring 应用中,IoC 容器掌握着主动权,调用者则变成了被动的一方,被动的等待 IoC 容器创建它所需要的对象(Bean)。
这个过程在职责层面发生了控制权的反转,把原本调用者通过代码实现的对象的创建,反转给 IoC 容器来帮忙实现,因此我们将这个过程称为 Spring 的“控制反转”。
2.IoC 的工作原理
在 Java 软件开发过程中,系统中的各个对象之间、各个模块之间、软件系统和硬件系统之间,或多或少都存在一定的耦合关系。
若一个系统的耦合度过高,那么就会造成难以维护的问题,但完全没有耦合的代码几乎无法完成任何工作,这是由于几乎所有的功能都需要代码之间相互协作、相互依赖才能完成。因此我们在程序设计时,所秉承的思想一般都是在不影响系统功能的前提下,最大限度的降低耦合度。
IoC 底层通过工厂模式、Java 的反射机制、XML 解析等技术,将代码的耦合度降低到最低限度,其主要步骤如下。
- 在配置文件(例如 Bean.xml)中,对各个对象以及它们之间的依赖关系进行配置;
- 我们可以把 IoC 容器当做一个工厂,这个工厂的产品就是 Spring Bean;
- 容器启动时会加载并解析这些配置文件,得到对象的基本信息以及它们之间的依赖关系;
- IoC 利用 Java 的反射机制,根据类名生成相应的对象(即 Spring Bean),并根据依赖关系将这个对象注入到依赖它的对象中。
由于对象的基本信息、对象之间的依赖关系都是在配置文件中定义的,并没有在代码中紧密耦合,因此即使对象发生改变,我们也只需要在配置文件中进行修改即可,而无须对 Java 代码进行修改,这就是 Spring IoC 实现解耦的原理。
3.结合例子理解IOC的解耦合
? ? ? ? 需求:创建一个类的对象并调用它的方法
????????原始方法:可以实现,但是耦合度太高了(两个类之间的联系太密切当其中一个类的信息改变,另一个类创建的对象也要跟着改变)
?????????工厂模式:解耦合,通过工厂模式降低了与UserDao的耦合度
????????但并不能降到最低限度。所以引入IOC,可以将耦合度降到最低
IOC过程:IOC思想是基于IOC容器完成的,IOC的容器底层就是对象工厂
?Spring提供IOC容器实现的两种方式(两个接口)
? ? ? ? 1.BeanFactory:IOC容器基本实现,是Spring内部使用的接口,不提供给开发人员使用,获取对象时创见对象
? ? ? ? 2.ApplicationContext:BeanFactory的子接口,提供更多更强大的的功能,一般由开发人员进行使用,加载配置文件时就会把配置文件对象进行创建。
? ? ? ? 3.ApplicationContext有两个实现类
????????????????ClassPathXmlApplicationContext:是src路径下的文件直接传文件名和后缀即可,加载类路径 ClassPath 下指定的 XML 配置文件,并完成 ApplicationContext 的实例化工作
????????????????FileSystemXmlApplicationContext:是盘下具体的一个文件,要把路径写清楚.加载指定的文件系统路径中指定的 XML 配置文件,并完成 ApplicationContext 的实例化工作
IOC操作Bean管理(依赖注入)
1.什么是Bean管理
? ? ? Bean管理是两个操作:Spring创建对象和注入属性
在了解了 IoC 之后,我们还需要了解另外一个非常重要的概念:依赖注入。
依赖注入(Denpendency Injection,简写为 DI)是 Martin Fowler 在 2004 年在对“控制反转”进行解释时提出的。Martin Fowler 认为“控制反转”一词很晦涩,无法让人很直接的理解“到底是哪里反转了”,因此他建议使用“依赖注入”来代替“控制反转”。
在面向对象中,对象和对象之间是存在一种叫做“依赖”的关系。简单来说,依赖关系就是在一个对象中需要用到另外一个对象,即对象中存在一个属性,该属性是另外一个类的对象。
例如,有一个名为 B 的 Java 类,它的代码如下。
public class B {
String bid;
A a;
}
从代码可以看出,B 中存在一个 A 类型的对象属性 a,此时我们就可以说 B 的对象依赖于对象 a。而依赖注入就是就是基于这种“依赖关系”而产生的。
我们知道,控制反转核心思想就是由 Spring 负责对象的创建。在对象创建过程中,Spring 会自动根据依赖关系,将它依赖的对象注入到当前对象中,这就是所谓的“依赖注入”。
2.IOC基于xml操作Bean管理
1、基于xml方式创建对象
????????? <!--配置User对象创建--> ? ????????<bean id=user class="comatguiguspring5.User"></bean> ?????????(1)在spring配置文件中,使用bean标签,标签里面添加对应属性,就可以实现对象创建 ? ???????(2)在bean标签有很多属性,介绍常用的属性 ?????????????????id属性:唯一标识 ?????????????????class属性:类全路径(包类路径) ?????????(3)创建对象时候,默认也是执行无参数构造方法完成对象创建
?2、基于xml方式注入属性-使用set方法进行注入
?(1)DI:依赖注入,就是注入属性 ? ? ? ? 第一种注入方式:使用set方法进行注入
第一步:创建类:定义属性和对应的set方法
public class Class02 {
// 创建属性
private String bname;
private String bauthor;
// 创建属性对应的set方法
public void setBname(String bname){
this.bname = bname;
}
public void setBauthor(String bauthor){
this.bauthor = bauthor;
}
public void testDemo(){
System.out.println(bname +","+bauthor);
}
}
第二步:在spring配置文件中配置对象创建,配置属性注入
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id = "book" class="com.java.spring5.Class02">
<!--使用property完成属性注入
name:类里面的属性名称
value:向属性注入值-->
<property name="bname" value="诗经"></property>
<property name="bauthor" value="三国演义"></property>
</bean>
</beans>
第三步:测试
public class Test02 {
@Test
public void testadd2(){
// 加载配置文件
ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
// 获取配置的创建
Class02 book = context.getBean("book",Class02.class);
System.out.println(book);
book.testDemo();
}
}
3.基于xml方式注入属性-使用有参数构造
????????第一步:创建类:定义属性,创建属性对应有参数的构造方法
public class Class03 {
private String name1;
private String bauthor1;
public Class03(String name1,String bauthor1){
this.bauthor1 = bauthor1;
this.name1 = name1;
}
// 使用有参构造器进行注入
public void testadd3(){
System.out.println(name1 +","+ bauthor1);
}
}
第二步:在spring配置文件中进行配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id = "book3" class="com.java.spring5.Class03">
<!--constructor-arg:完成有参注入-->
<constructor-arg name="name1" value="活着"></constructor-arg>
<constructor-arg name="bauthor1" value="烟草"></constructor-arg>
</bean>
</beans>
第三步:测试
public class Test03 {
@Test
public void testaddd(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean3.xml");
Class03 book3 = context.getBean("book3",Class03.class);
System.out.println(book3);
book3.testadd3();
}
}
4、IOC操作Bean管理xml注入其他类型属性
(1)null值
<property name = "address><null/></property>
?(2)属性值包含特殊符号
? ?1把<>进行转义<: >: ? ? 2把带特殊符号内容写到CDATA ?
? <property name="address"
? ? <value><![CDATA[<<南京>>]]value></property>?
4.基于xml方式注入属性-外部注入bean方式注入属性
1)创建两个类service类和dao类
- ????????创建userDao属性并创建他的set方法
(2)在service调用dao里面的方法????????
????????在配置文件中创建service对象
????????创建userdao的对象
????????注入UserDao的属性
(3)在spring配置文件中进行配置。
public class UserService
//创建UserDao类型属性,生成set方法
private UserDao userDao:
public void setuserDao (UserDao userDao) {
this. userDao = userDao:
}
public void add(
System.out println(service add)
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userService" class="com.java.spring5.service.UserService">
<!--注入UserDao的属性
name属性:类里面的属性名称
ref:创建userDao对象的bean标签,和下边的name值相同-->
<property name="userDao" ref="userdao"></property>
</bean>
<bean id="userdao" class="com.java.spring5.dao.UserDaoEmp"></bean>
</beans>
5.基于xml方式注入属性-内部bean和级联赋值注入属性的方法
?(1)一对多关系:部门和员工 一个部门有多个员工,一个员工属于一个部门,部门是一,员工是多
(2)在实体类之间表示一对多关系,员工表示所属部门,使用对象类型属性进行
(3)在spring中配置
(4)测试
内部bean
//员工类
public class Emp {
private Dept dept;
public void setDept(Dept dept){
this.dept = dept;
}
@Override
public String toString() {
return "Emp{" +
"dept=" + dept +
'}';
}
public void test(){
System.out.println(dept);
}
}
//部门类
public class Dept {
@Override
public String toString() {
return "Dept{}";
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--内部bean-->
<bean id="emp" class="com.java.spring5.bean.Emp">
<!-- 设置两个普通属性-->
<property name="ename" value="lucy"></property>
<property name="gender" value="女"></property>
<!-- 设置对象类型属性-->
<property name="dept" >
<bean id="dept" class="com.java.spring5.bean.Dept">
<property name="dname" value="安保部"></property>
</bean>
</property>
</bean>
</beans>
?级联赋值的两种写法
1
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="emp" class="com.java.spring5.bean.Emp">
<!-- 设置两个普通属性-->
<property name="ename" value="lucy"></property>
<property name="gender" value="女"></property>
<!-- 级联赋值-->
<property name="dept" ref="dept1" ></property>
</bean>
<bean id="dept1" class="com.java.spring5.bean.Dept">
<property name="dname" value="财务部"></property>
</bean>
</beans>
? ? ? ? 输出:lucy 女 财务部
2
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="emp" class="com.java.spring5.bean.Emp">
<!-- 设置两个普通属性-->
<property name="ename" value="lucy"></property>
<property name="gender" value="女"></property>
<!-- 级联赋值-->
<property name="dept" ref="dept1" ></property>
<!-- Emp类里有两个字符串属性,一个对象属性,对象属性中的Dept里有一个属性dname,
调用它在这里就可以给他赋值,但不能直接调用,要现在Emp中得到这个对象,及生成dept属性的get方法-->
<property name="dept.dname" value="技术部"></property>
</bean>
<bean id="dept1" class="com.java.spring5.bean.Dept">
<property name="dname" value="财务部"></property>
</bean>
</beans>
6.xml注入集合属性
- 注入数组类型属性
- 注入List集合属性
- 注入Map集合类型
- 注入 set集合
? ? ? ? 第一步:创建类,定义数组、list、map、set类型属性,生成对应的set方法
public class Stu {
// 数组类型属性
private String[] courses;
// List集合类型属性
private List<String> list;
// Map集合类型shuxing
private Map<String,String> maps;
// set集合类型属性
private Set<String> sets;
// 学生所学的多门的课程
private List<Course>courseList;
public void setCourseList(List<Course> courseList) {
this.courseList = courseList;
}
public void setSets(Set<String> sets) {
this.sets = sets;
}
public void setCourses(String[] courses) {
this.courses = courses;
}
public void setList(List<String> list) {
this.list = list;
}
public void setMaps(Map<String, String> maps) {
this.maps = maps;
}
public void test(){
System.out.println(Arrays.toString(courses));
System.out.println(list);
System.out.println(maps);
System.out.println(sets);
System.out.println(courseList);
}
}
public class Course {
private String cname;
public void setCname(String cname) {
this.cname = cname;
}
@Override
public String toString() {
return "Course{" +
"cname='" + cname + '\'' +
'}';
}
}
? ? ? ? 第二步:在spring配置文件进行配置
- ?数组类型属性注入 标签array
- ?list属性注入 ?标签list
- Map属性注入 标签map、 entry
- set属性注入 标签set
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="stu" class="com.java.spring5.collectiontype.Stu">
<!-- 数组类型属性注入 标签array-->
<property name="courses">
<array>
<value>java</value>
<value>数据库</value>
</array>
</property>
<!-- list属性注入 标签list-->
<property name="list">
<list>
<value>张三</value>
<value>李四</value>
</list>
</property>
<!-- Map属性注入 标签map entry---->
<property name="maps">
<map>
<entry key="JAVA" value="java"></entry>
<entry key="PHP" value="php"></entry>
</map>
</property>
<!-- set属性注入 标签set-->
<property name="sets">
<set>
<value>mysql</value>
<value>redies</value>
</set>
</property>
</bean>
</beans>
测试
public class Testc1 {
@Test
public void testCollectin1(){
ApplicationContext context = new ClassPathXmlApplicationContext("beanc1.xml");
Stu stu = context.getBean("stu", Stu.class);
stu.test();
}
}
但集合属性要考虑两个细节
第一个细节:刚刚创建的都是String属性,如果我想在集合理放对象怎么放
第二个细节:上述集合只能在id=stu中使用,不能再其他部分适用,如何提取集合将他变成公共部分
第一个细节(list为例)
?(1)创建多个对象,和上述第一步创建内容一样
?(2)注入属性
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--注入list集合类型-->
<bean id="cou" class="com.java.spring5.collectiontype.Stu">
<property name="courseList">
<list>
<!-- 不是注入普通值,注入对象值标签ref-->
<ref bean="course1"></ref>
<ref bean="course2"></ref>
</list>
</property>
</bean>
<bean id="course1" class="com.java.spring5.collectiontype.Course">
<property name="cname" value="Spring5"></property>
</bean>
<bean id="course2" class="com.java.spring5.collectiontype.Course">
<property name="cname" value="Mybatis"></property>
</bean>
</beans>
(3)测试
public class Testc2 {
@Test
public void testCollection2(){
ApplicationContext context = new ClassPathXmlApplicationContext("beanc2.xml");
Stu stu = context.getBean("cou",Stu.class);
stu.test();
}
}
?
第二个细节
(1)创建多个对象,和上述第一步创建内容一样
?(2)创建提取类book
//提取类
public class Book {
private List<String> list;
public void setList(List<String> list) {
this.list = list;
}
@Override
public String toString() {
return "Book{" +
"list=" + list +
'}';
}
public void test3(){
System.out.println(list);
}
}
?(3)在spring配置文件中引入名称空间util(注意上面xmlns和xsi配置)
<?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: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">
<!--提取list集合类型属性注入-->
<util:list id="bookList">
<value>诗</value>
<value>词</value>
<value>歌</value>
</util:list>
<!-- 提取list集合类型属性注入-->
<bean id="book" class="com.java.spring5.collectiontype.Book">
<property name="list" ref="bookList"></property>
</bean>
</beans>
(4)测试
public class Testc3 {
@Test
public void testCollectin3(){
ApplicationContext context = new ClassPathXmlApplicationContext("beanc3.xml");
Book bo = context.getBean("book", Book.class);
bo.test3();
}
}
7.工厂bean-FactoryBean?
? ? ? ?1、Spring有两种类型bean,一种普通bean,另外一种工厂bean-FactoryBean? ? ? ? ? 2、普通bean:在配置文件中定义bean类型就是返回类型(上面的就是普通的) ? ? ? ? 3、工厂bean:在配置文件定义bean类型可以和返回类型不一样 ? ? ? ? ? ? ?第一步创建类,让这个类作为工厂bean,实现接口FactoryBean?
??????????????第二步实现接口里面的方法,在实现的方法中定义返回的bean类型
//实现factorybean实现接口
public class MyBean implements FactoryBean<Course> {
//返回类型方法,你定义的类型和返回类型不一样是由此方法决定
// 类里定义的是MyBean类型,返回Course类型
@Override
public Course getObject() throws Exception {
Course course = new Course();
course.setCname("abc");
return course;
}
//返回类型
@Override
public Class<?> getObjectType() {
return null;
}
//是否是一个单例
//单例:所有请求都有一个对象来处理,因为没必要每个请求都建一个对象
@Override
public boolean isSingleton() {
return FactoryBean.super.isSingleton();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="mybean" class="com.java.spring5.factorybean.MyBean"></bean>
</beans>
public class Testf1 {
@Test
public void testf1(){
ApplicationContext context = new ClassPathXmlApplicationContext("beanf.xml");
// 注意.class调用的类名,是返回值的类型
Course mybean = context.getBean("mybean", Course.class);
System.out.println(mybean);
}
}
?8.bean创建单例和多利
在Spring里,默认情况下,bean是单例
?????????Book1和?Book2输出内容相同
如何设置单例还是多例 (1)在spring配置文件bean标签里面有属性(scope)用于设置单实例还是多实例 (2)scope属性值 第一个值默认值,singleton,表示是单实例对象 第二个值prototype,表示是多实例对象
singleton和prototype区别 第一 singleton单实例,prototype多实例 第二设置scope值是singleton时候,加载spring配置文件时候就会创建单实例对象+ ? ? ???设置scope值是prototype时候,不是在加载spring配置文件时候创建对象,在调用getBean方法时候创建多实例对象?
8.、bean生命周期
生命周期 ?(1)从对象创建到对象销毁的过程 ?2、bean生命周期,无后置配置处理器时 ?(1)通过构造器创建bean实例(无参数构造) ?(2)为bean的属性设置值和对其他bean引用(调用set方法) ? (3)调用bean的初始化的方法(需要进行配置初始化的方法) ? (4)bean可以使用了(对象获取到了) ? (5)当容器关闭时候,词用bean的销毁的方法(需要进行配置销毁的方法)
public class Orders {
private String oname;
public Orders() {
System.out.println("第一步:执行无参构造器创建bean实例");
}
public void setOname(String oname) {
this.oname = oname;
System.out.println("第二步:调用set方法设置属性值");
}
// 创建执行初始化的方法,但这只是一个普通的方法不会自己执行所以我们要进行配置
public void initMethod(){
System.out.println("执行初始化的方法");
}
// 销毁方法
public void destory(){
System.out.println("第五步:这是一个销毁方法");
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- init-method:方法名字:配置初始化方法
destory-method:方法名字:执行销毁方法-->
<bean id="orders" class="com.java.spring5.bean.Orders" init-method="initMethod" destroy-method="destory">
<property name="oname" value="手机"></property>
</bean>
</beans>
public class Testl1 {
@Test
public void life(){
// ApplicationContext不能调用close方法他的子类可以ClassPathXmlApplicationContext
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beanl1.xml");
Orders orders = context.getBean("orders", Orders.class);
System.out.println("第四步:获取创建bean实例对象");
System.out.println(orders);
// 手动销毁bean实例才能让配置调用
context.close();
}
9.Bean的后置处理器?
bean有后置处理器,bean生命周期有七步 ?(1)通过构造器创建bean实例(无参数构造) ?(?2)为bean的属性设置值和对其他bean引用(调用set方法)t ?(3)把bean实例传递bean后置处理器的方法postProessAfternitialization
?(4)调用bean的初始化的方法(需要进行配置初始化的方法) (5))把bean实例传递bean后置处理器的方法postProessAfternitialization (6)bean可以使用了(对象获取到了) (7)当容器关闭时候,调用bean的销毁的方法(需要进行配置销毁的方法) 演示添加后置处理器效果 1)创建类,实现接口BeanPostProessor 创建后置处理器
public class Orders {
private String oname;
public Orders() {
System.out.println("第一步:执行无参构造器创建bean实例");
}
public void setOname(String oname) {
this.oname = oname;
System.out.println("第二步:调用set方法设置属性值");
}
// 创建执行初始化的方法,但这只是一个普通的方法不会自己执行所以我们要进行配置
public void initMethod(){
System.out.println("执行初始化的方法");
}
// 销毁方法
public void destory(){
System.out.println("第五步:这是一个销毁方法");
}
}
public class MyBeanFost implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("这是初始化之前执行的方法");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("这是初始化之后执行的方法");
return bean;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- init-method:方法名字:配置初始化方法
destory-method:方法名字:执行销毁方法-->
<bean id="orders" class="com.java.spring5.bean.Orders" init-method="initMethod" destroy-method="destory">
<property name="oname" value="手机"></property>
</bean>
<!-- 配置后置处理器,会给上边创建的所有bean实例配置后置处理器-->
<!-- 应为实现了接口,spring就会把他当做后置处理器执行-->
<bean id="myBeanPost" class="com.java.spring5.bean.MyBeanFost"></bean>
</beans>
public class Testl1 {
@Test
public void life(){
// ApplicationContext不能调用close方法他的子类可以ClassPathXmlApplicationContext
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beanl1.xml");
Orders orders = context.getBean("orders", Orders.class);
System.out.println("第四步:获取创建bean实例对象");
System.out.println(orders);
// 手动销毁bean实例才能让配置调用
context.close();
}
?
10.xml自动装配
什么是自动装配 (1)根据指定装配规则(属性名称或者属性类),Spring自动将匹配的属性值进行注入?
根据属性名或类型自动注入?
?第一步:创建类和属性
public class Emp {
private Dept dept;
public void setDept(Dept dept){
this.dept = dept;
}
@Override
public String toString() {
return "Emp{" +
"dept=" + dept +
'}';
}
public void test(){
System.out.println(dept);
}
}
public class Dept {
@Override
public String toString() {
return "Dept{}";
}
}
?第二步:配置xml属性
?实现自动装配 ? ? ? ? bean标签属性autowire实现自动装配 ? ? ? ? 这个属性有两个值:byName根据属性名称注入,注入bean的值必须和类的属性名称一样 ? ? ? ? byType:根据属性类型注入,同一个类型只能注册一次
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--一个员工对应一个部门,所以将部门注入给员工-->
<!-- 实现自动装配
bean标签属性autowire实现自动装配
这个属性有两个值:byName根据属性名称注入,注入bean的值必须和类的属性名称一样
byType:根据属性类型注入,同一个类型只能注册一次-->
<bean id="emp" class="com.java.spring5.autowire.Emp" autowire="byName">
<!-- 手动注入 <property name="dept" ref="dept1"></property>-->
</bean>
<!-- 注入bean的值必须和类的属性名称一样-->
<bean id="dept" class="com.java.spring5.autowire.Dept" ></bean>
<!-- 再加上下面那句,使用bytype就会报错,因为和上面的bean是同一个类型(Dept),但byname不会-->
<!-- <bean id="dept1" class="com.java.spring5.autowire.Dept"></bean>-->
</beans>
11.? ? ?IOC操作Bean管理(外部属性文件-数据库)
? ? ? ? ??1、直接配置数据库信息 ? ? ? ? ? ? ? ? 1)配置德鲁伊连接池 ? ? ? ? ? ? ? ? ?2)引入德鲁伊连接池依赖jar包
? ? ? ???????? 2.引入外部属性文件配置数据库连接池
? ? ? ? ? ? ? ? 1)创建外部属性文件,properties格式文件,写数据库信息
prop.driverClass=com.mysql.cj.jdbc.Driver
prop.url=jdbc:mysql://localhost:3306/test
prop.name=root
prop.password=123456
? ? ? ? ? ? ? ? 2)把外部properties属性文件引入到Spring配置文件中
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
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/beans/spring-context.xsd">
<bean id="dtaSocutse" class="com.alibaba.druid.pool.DruidDataSource">
<!--直接配置未使用配置文件-->
<!-- 固定的值:driverClassName驱动名称,
url:数据库地址-->
<!-- <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>-->
<!-- <property name="url" value="jdbc:mysql://localhost:3306/test"></property>-->
<!-- <property name="username" value="root"></property>-->
<!-- <property name="password" value="123456"></property>-->
<!-- 配置文件配置连接池-->
<property name="driverClassName" value="${prop.driverClass"></property>
<property name="url" value="${prop.url"></property>
<property name="username" value="${prop.name"></property>
<property name="password" value="${prop.password"></property>
</bean>
</beans>
?基于注解方式操作bean管理
? ? ?1、什么是注解
? ? ? ? ? 1)注解是代码特殊标记,格式:@注解名称(属性名称=属性值,属性名称=属性值..) ? ? ? ? ? ?2)使用注解,注解作用在类上面,方法上面,属性上面 ? ? ? ? ? ?3)使用注解目的:简化xml配置
? ? 2.Spring针对Bean管理中创建对象提供注解
? ? ? ? ?1)@Component:普通组建利用它都可以创建对象 ? ? ? ? ? 2)@Service:一般用在业务逻辑和service层 ? ? ? ? ? 3)@Controllei:用在web层 ? ? ? ? ?4)@Repository:dao层
四者使用时没什么区别,都是用来创建对象的且参数都为value,value为此bean的名字可不写,默认为第一个字母为小写的类名
3、基于注解方式实现对象创建
第一步引入依赖
第二步开启组件扫描
context:component-scan:关键字扫描
base-package:要扫描的包名 ? ?如果扫多个包,多个包使用号隔开? 或扫描包上层目录
<context:component-scan base-package="com.java.spring5"></context:component-scan>
第三步创建类,在类上面添加创建对象注解
?在注解里面value属性值可以省略不写,
?默认值是类名称,首字母小写
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
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:component-scan base-package="com.java.spring5"></context:component-scan>
</beans>
//使用注解创建对象可使用四个注解中任何一个
//在注解里面的value可以省略不写,他会默认类名的首字母小写
@Service(value = "userService")
public class UserService {
// 定义dao属性不需要添加set方法,添加属性注解即可
public void add(){
System.out.println("service add....");
}
}
?测试
public class TestZhujie {
@Test
public void testServices(){
ApplicationContext context = new ClassPathXmlApplicationContext("beanzhu1.xml");
// 这里不在是id值,因为value值相当于id值
UserService userService = context.getBean("userService", UserService.class);
System.out.println(userService);
userService.add();
}
}
?细节:扫描类的选择
红色:扫描包中的所有类
彩色:扫描Controller注解中的所有类
?
其中type有annotation,aspectj,assignable,custom,regex几种类型。
其意义如下:?
annotation:注解类型 assignable_type:annotation:指定的类型 aspectj:按照Aspectj的表达式,基本上不会用到 regex:按照正则表达式 custom:自定义规则
4、基于注解方式实现属性注入
(1)@Autowired:根据属性类型进行自动装配 ?(2)@Qualifier:根据属性名称进行注入 ?(3) @Resource: 可以根据类型注入,可以根据名称注入 ? (4) @value:注入普通类型属性
5、基于注解方式实现属性注入
(1)@Autoired根据属性类型进行自动装配 第一步service和dao对象创建,在senvice和dao类添加创建对象注解(@Service?@Repository )
第二步在service注入da0对象,在sevice类添加dao类型属性,在属性上面使用注解(? ?@Autowired)
@Service
public class UserService {
// 定义接口属性,不需要添加set方法,添加注入属性注解
@Autowired
private UserDao userDao;
public void add(){
System.out.println("service add...");
userDao.add1();
}
}
public interface UserDao {
public void add1();
}
@Repository
public class UserDaoEmp1 implements UserDao {
@Override
public void add1() {
System.out.println("dao");
}
}
测试
public class Test1 {
@Test
public void testServices(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
// 这里不在是id值,因为value值相当于id值
UserService userService = context.getBean("userService", UserService.class);
System.out.println(userService);
userService.add();
}
}
?(2)@Qualifier:根据属性名称进行注入(但必须结合@Autowired使用)
?????????当有多个接口实现类时Autowired没有办法确定是哪个实现类。所以结合@Qualifier根据名称进行注解
(3)? @Resource: 可以根据类型注入,可以根据名称注入
?
?4) @value:注入普通类型属性
? ? ? ?输出:? ?name = abc?
完全注解开发(了解SpringBoot会真正涉及)
????????
|