文章目录
目录
三 IOC容器
3.1 IOC容器概述
什么是IOC: 是一个中间容器,即“控制反转”,不是什么技术,而是一种设计思想。Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。
如何理解好Ioc呢?理解好Ioc的关键是要明确“谁控制谁,控制什么,为何是反转(有反转就应该有正转了),哪些方面反转了”,那我们来深入分析一下:
谁控制谁,控制什么:传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对 象的创建;谁控制谁?当然是IoC 容器控制了对象;控制什么?那就是主要控制了外部资源获取(不只是对象包括比如文件等)。
为何是反转,哪些方面反转了:有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。
IOC三个核心:
- XML解析
- 工厂模式
- 反射-----康师傅王振国
IOC接口:提供IOC容器实现的两种方式
ApplicationContext | 是BeanFactory的子接口,一般由开发人员使用,加载配置文件时就会创建对象 |
---|---|
BeanFactory | 是Spring内部使用的接口,不建议开发人员使用,加载配置文件时不会创建对象,再获取对象时才会创建 |
3.2 IOC Bean管理操作
在spring xml 配置文件中,使用bean标签,标签里添加对应的属性,就可以实现对象的创建,创建对象时,也是默认执行无参构造方法完成对象创建。
3.2.1bean标签的常用属性:
id:是bean的唯一标识,相当于起别名; class:指定bean的具体实现类,使用类的全限定名(包类路径); property:< bean >的子元素,用于调用bean实例中的setter方法完成属性赋值,从而完成依赖注入。该元素的name属性指定bean实例中的属性名,ref属性或value属性用于指定参数值; constructor-arg:< bean >元素的子元素,用于构造器实例化时完成依赖注入; |
---|
3.2.2属性值的两种方式
正常赋属性值(正转)
package com.pan.spring5;
public class User {
private String uName;
public void setuName(String uName) {
this.uName = uName;
}
public static void main(String[] args) {
User user = new User();
user.setuName("张胜志");
}
}
通过IOC容器调用属性值
公共方法类
package com.pan.spring5;
public class User {
private String uName;
private int age;
public void setAge(int age) {
this.age = age;
}
public void setuName(String uName) {
this.uName = uName;
}
public void teatDemo(){
System.out.println(uName+"......"+age);
}
}
XML配置文件,赋属性值,并创建好公共方法的对象
<bean id="user" class="com.pan.spring5.User">
<property name="uName" value="潘胜志"></property>
<property name="age" value="20"></property>
</bean>
调用IOC容器类
package com.pan.spring5.testdemo;
import com.pan.spring5.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestSpring5 {
@Test
public void testAdd(){
// 1.加载spring配置文件
ApplicationContext context =
new ClassPathXmlApplicationContext("bean1.xml");
//2.获取配置创建的对象,这里就不需要new 一个对象了可以直接获取
User user = context.getBean("user", User.class);
System.out.println(user);
user.teatDemo();
}
}
有参构造注入
package com.pan.spring5;
public class Orders {
private String oname;
private String address;
//有参构造
public Orders(String oname,String address) {
this.address=address;
this.oname=oname;
}
public void testDemo2(){
System.out.println(address+":::::"+oname);
}
}
xml:有参构造注入constructor-arg name value.
<bean id="orders" class="com.pan.spring5.Orders">
<constructor-arg name="oname" value="abc"></constructor-arg>
<constructor-arg name="address" value="china"></constructor-arg>
</bean>
P名称空间注入
作用简化了注入属性
给p标签一个空间,既可以直接到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"
<!-- 给予一个p标签的空间 -->
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">
注入属性:
<bean id="user" class="com.pan.spring5.User" p:uanme = "张万森" ,P:age = "20"> </bean>
3.2.3 Ioc注入其他类型属性
空值设置
<bean id="user" class="com.pan.spring5.User">
<property name="age"><null/></property>
<property name="uName" value="潘胜志"></property>
<!-- <property name="age" value="20"></property>-->
</bean>
属性值中包含特殊符号,要么转义,要么使用将内容写到CDATA中
<property name="age">
<value>
<![CDATA[<<19>>]]>
</value>
</property>
3.2.4 在配置文件中注入其他对象 ref = " 配置里创建的对象"(注入内部bean)
<bean>
<property name = "dept" ref = "dept"></property>
</bean>
<bean id = "dept" class = "com.pan.spring5.bean.Dept">
<property name = "dname" value = "财务部"></property>
</bean>
ref 将另外一个bean 创建的对象引入同一个bean里
作用:当测试类调用时,会将其他类的属性一并合并运行
3.2.5 级联赋值
第一种:在内部bean注入属性
<bean id = "emp" class = "com.pam.spring5.Emp">
<property name = "ename" value = "lucy"></property>
<property name = "gender" value = "女"></property>
<!-- 级联赋值 -->
<property name = "dept" ref = "dept"></property>
<!--在内部注入属性-->
<property name = "dept.dname" value = "技术部"></property>
</bean>
<bean id = "dept" class = "com.pan.spring5.bean.Dept"></bean>
第二种方法:在外部注入bean属性
<bean id = "dept" class = "com.pan.spring5.bean.Dept">
<property name = "dname" value = "财务部"></property>
</bean>
3.2.6属性注入(map,list,数组)
package com.lc.collection;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public class Department {
private String name;
private String [] empName;//数组
private List<Employee> empList;//list集合
private Set<Employee> empsets;//set集合
private Map<String,Employee> empMaps;//map集合
private Properties pp;//Properties的使用
public Set<Employee> getEmpsets() {
return empsets;
}
public void setEmpsets(Set<Employee> empsets) {
this.empsets = empsets;
}
public String[] getEmpName() {
return empName;
}
public void setEmpName(String[] empName) {
this.empName = empName;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Employee> getEmpList() {
return empList;
}
public void setEmpList(List<Employee> empList) {
this.empList = empList;
}
public Map<String, Employee> getEmpMaps() {
return empMaps;
}
public void setEmpMaps(Map<String, Employee> empMaps) {
this.empMaps = empMaps;
}
public Properties getPp() {
return pp;
}
public void setPp(Properties pp) {
this.pp = pp;
}
}
xml 配置文件
<?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:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<bean id="department" class="com.hsp.collection.Department">
<property name="name" value="财务部"/>
<!-- 给数组注入值 -->
<property name="empName">
<list>
<value>小明</value>
<value>小明小明</value>
<value>小明小明小明小明</value>
</list>
</property>
<!-- 给list注入值 list 中可以有相当的对象 -->
<property name="empList">
<list>
<ref bean="emp2" />
<ref bean="emp1"/>
<ref bean="emp1"/>
<ref bean="emp1"/>
<ref bean="emp1"/>
<ref bean="emp1"/>
<ref bean="emp1"/>
</list>
</property>
<!-- 给set注入值 set不能有相同的对象 -->
<property name="empsets">
<set>
<ref bean="emp1" />
<ref bean="emp2"/>
<ref bean="emp2"/>
<ref bean="emp2"/>
<ref bean="emp2"/>
</set>
</property>
<!-- 给map注入值 map只有key不一样,就可以装配value -->
<property name="empMaps">
<map>
<entry key="11" value-ref="emp1" />
<entry key="22" value-ref="emp2"/>
<entry key="22" value-ref="emp1"/>
</map>
</property>
<!-- 给属性集合配置 -->
<property name="pp">
<props>
<prop key="pp1">abcd</prop>
<prop key="pp2">hello</prop>
</props>
</property>
</bean>
<bean id="emp1" class="com.hsp.collection.Employee">
<property name="name" value="北京"/>
<property name="id" value="1"/>
</bean>
<bean id="emp2" class="com.hsp.collection.Employee">
<property name="name" value="天津"/>
<property name="id" value="2"/>
</bean>
</beans>
3.2.7 bean的作用域
spring默认的bean是单实例对象
设置单多实例对象 - 属性 scope 实现
- scope 属性值
- singleton , 表示单实例对象
- protoptype ,多实例对象
- request ,把这个值变成一个请求
- session , 把这个之变成一个会话保存
3.2.8 bean 的生命周期
- 创建bean实例 ,通过构造器创建bean实例(无参构造)
- 为bean的属性设置和对其他bean的引用(调用set的方法)
- 调用bean的初始化方法(需要配置)
- bean获取(对象获取到了)
- 关闭容器,调用bean 的销毁方法(需要进行配置方法)
生命周期代码示例
创建方法类。
package com.pan.spring5.methodclass;
public class Orders {
private String oname;
private String address;
//有参构造
//无参构造
public Orders(){
System.out.println("第一步 默认执行了无参构造,创建了bean 的实例");
}
//设置属性值的方法
public void setAddress(String address) {
this.address = address;
System.out.println("第二步 设置了oname 的属性值");
}
//设置属性值的方法
public void setOname(String oname) {
this.oname = oname;
System.out.println("第三步 设置了address 的属性值");
}
//创建初始化方法
public void initMethod(){
System.out.println("第四步 执行了初始化方法");
}
//销毁方法
public void destroyMethod(){
System.out.println("第六步 销毁bean创建的实例");
}
}
创建对象和执行方法的XML文件
- init-method destroy-method
<bean id="orders" class="com.pan.spring5.methodclass.Orders" init-method="initMethod" destroy-method="destroyMethod">
<property name="oname" value="电脑"></property>
<property name="address" value="电脑"></property>
</bean>
调用测试类
@Test
public void testOrders(){
ApplicationContext context =
new ClassPathXmlApplicationContext("com/pan/spring5/beanpackage/bean2.xml");
Orders orders = context.getBean("orders", Orders.class);
System.out.println("第五步 获取创建bean的实例对象");
System.out.println(orders);
orders.testDemo2();
//销毁bean,多态向下转型,调用close方法
((ClassPathXmlApplicationContext) context).close();
}
3.3.9 bean的后置处理器
- 创建bean实例 ,通过构造器创建bean实例(无参构造)
- 为bean的属性设置和对其他bean的引用(调用set的方法)
- 调用bean的后置处理器将实例传递给后置处理器
- 调用bean的初始化方法(需要配置)
- bean获取(对象获取到了)
- 关闭容器,调用bean 的销毁方法(需要进行配置方法)
创建后置处理器
-
创建类,实现接口BeanPostProcessor ,创建后置处理器
-
//代码展示 package com.pan.spring5; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; public class MyBean 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; } }
-
<!-- 配置后置处理器 --> <bean id = "myBeanpost" class = "com.pan.spring5.methodclass.MyBean"></bean>
3.3.Bean自动装配
概念理解:自动装配指的是,根据指定装配规则(属性名称或属性类型),spring自动将匹配的属性值进行注入
演示代码
byName byType
引入外部文件
自动装配
注解配置
外部属性文件
直接配置数据库信息
-
配置德鲁伊连接池
-
直接配置
-
引入德鲁伊jar包-----放入lib包中--------->在引入depedencey中 druid-1.1.5.jar
-
连接池配置
<bean id = "datasource" class = "com.pan.spring5.DruidDataSource"> <property name = "driverClaassName" value = "com.mysql.jdbc.Driver"></property> <property name = "url" value = "jdbc:mysql://localhost:3306/userDB"></property> <property name = "username" value = "root"></property> <property name = "password" value = "123456"></property> </bean>
-
-
引入外部属性文件配置数据库连接池
-
床架你外部属性文件,property的配置信息
-
prop.driverClass = com.pan.spring5.DruidDataSource prop.url = jdbc:mysql://localhost:3306/userDB prop.username = root prop.password = 123456
配置文件
-
xml 文件配置
xmlns:context=“http://www.springframework.org/schema/context”
http://www.springframework.org/schema/beans/spring-context.xsd"
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <!-- 给予一个p标签的空间 --> xmlns:p="http://www.springframework.org/schema/p" 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/beans/spring-context.xsd"> <!-- 引入外部文件 --> <context:property-placeholder lacation = "classpath:jdbc.properties"/> <bean id = "datasource" class = "com.pan.spring5.DruidDataSource"> <property name = "driverClaassName" value = "${prop.driverClass}"></property> <property name = "url" value = "${prop.url}"></property> <property name = "username" value = "${prop.username}"></property> <property name = "password" value = "${prop.password}"></property> </bean>
${} 用这个表达式引入外部文件属性值
-
-
3.4 IOC操作bean管理(基于注解方式)
1**.什么是注解**:注解是代码的特殊标记,格式:@注解名称(属性名称 = 属性值,属性名称 =属性值 …)
注解的使用:注解作用在类方面,方法上面,属性上面
使用注解的目的:简化xml配置
2.Spring针对Bean管理中创建对象提供的注解
- @Component 泛指各种组件 以下几种都可称为 @Component
- @Service 业务层
- @Controller 控制层
- @Respository 数据访问层
上面的注解都是一样的,都可以用来创建bean的实例
3.4.1基于注解方式实现对象创建
-
引入jar包 spring-aop-5.2.6.RELEASE.jar
-
开启组件扫描(开启注解支持)
-
如果扫描多个包,多个包使用逗号隔开
-
或者扫描包的上层目录
<context-component-scan base-package = "com.pan"></context-component-scan>
-
3.创建类,在类上面添加创建对象注解
-
在注解里value的值可以省略
-
默认值是类名称,首字母都会转成小写
<!-- use-default-filters = "false" 将过滤器改为自行配置 --> <!-- context:include-filter 设置扫描内容 --> <context-component-scan base-package = "com.pan" use-default-filters = "false"> <context:include-filter type = "annotation" experssion = "com.pam.Controller"/> </context-component-scan>
3.4.2 基于注解方式实现属性的注入
- @Autowired:根据属性类型自动装配
- 首先了IOC操作bean管理 ,bean管理是指创建对象,注入属性。当我们将一个类上标注@Service ,@Cotroller ,@Component ,等待注解后,spring的组件扫描自动发现他 并将其初始化为spring应用上下文的bean .
- 当这个类被使用时,加了注解 @autowriter 时 ,会自动创建bean,以致使用。
- 作用 :可以标注在属性上,方法上,和构造器上,来完成自动装,根据属性值类型来判断。
- 使用:它可以标注在属性上,方法和构造器上,那它们有何区别呢,简单来说是他们的初始化顺序不同,推荐对构造器上使用,如果在接口上使用,其注入的是接口的实现类,实现类很多这时就需要根据属性名称来找到这个bean
- @Qualifier:根据属性名称进行注入 ==========依据其上便都可以解释
- @Resource:可以根据类型注入,可以根据名称注入
- @Value:注入普通类型属性