文章目录
IoC
原理
Inversion of Control 控制反转,是一种编程思想,目的解耦合
实现
xml + 工厂模式 + 反射
所需基本jar包
1、IoC初始化
-
Spring Ioc
容器用来创建和管理类的实例称为Bean
-
BeanFactory
和ApplicationContext
是Spring进行对象管理的主要接口
1.1、ApplicationContext初始化方式
XML配置的ApplicationContext
实现类,包括ClassPathXmlApplicationContext
和 FileSystemXmlApplicationContext
ClassPathXmlApplicationContext 是从类的根目录开始读
FileSystemXmlApplicationContext则默认从项目根目录开始读
classpath:
表示类的根路径(idea的src),如果classpath*:
则除了自身的类路径之外,同时也会查找依赖库(.jar)下的目录
// ClassPathXmlApplicationContext
ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
// FileSystemXmlApplicationContext
ApplicationContext fileSystemXmlApplicationContext = new FileSystemXmlApplicationContext("classpath:applicationContext.xml");
😤细🔒,比如这里,我们需要读的src/com/flzj/test/applicationContext2.xml
ApplicationContext fileSystemXmlApplicationContext = new FileSystemXmlApplicationContext("src/com/flzj/test/applicationContext2.xml");
1.2、Spring基于XML的配置文件结构
①
xmlns : 是XML Namespace
的缩写,和C++ 的 namespace
差不多一个作用
xmlns:xis : 表示使用xsi作为前缀的命名空间,这个属性是为了下面的xsi:schemaLocation
的定义
②
xsi:schemaLocation :用于定义命名空间对应的XSD
(XML结构定义)文档的位置关系,两者是成对存在的
Schema
Schema处理器将从指定位置读取Schema
文档,根据描述的文档结构验证XML文件是否符合规范
2、Bean管理
2.1、Bean的配置
<bean>
标签的 id
和 class
属性
<bean id="person" class="com.flzj.bean.Person"></bean>
.getBean()
方法
@Test
public void test1(){
// 获取Bean对象
ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person = classPathXmlApplicationContext.getBean("person",Person.class); // getBean()
System.out.println(person);
}
2.2、Bean注入
2.2.1、set注入
<property> 标签 ,name
属性 ,value
属性
<bean id="person" class="com.flzj.bean.Person">
<property name="name" value="aaa"></property>
<property name="age" value="100"></property>
</bean>
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
2.2.2、有参构造器注入
<constructor-arg> 标签 name
属性 value
属性
<bean id="person" class="com.flzj.bean.Person">
<constructor-arg name="name" value="ccc"></constructor-arg>
<constructor-arg name="age" value="18"></constructor-arg>
</bean>
public Person(String name, int age) {
this.name = name;
this.age = age;
}
2.2.3、P名称空间注入(了解)
底层还是set
2.2.4、注入空值
标签
<bean id="person" class="com.flzj.bean.Person">
<property name="name">
<null/>
</property>
<property name="age" value="123">
</property>
</bean>
2.2.5、特殊符号
<![CDATE[奇奇怪怪的符号]]>
<bean id="person" class="com.flzj.bean.Person">
<property name="name">
<value><![CDATA[<<特殊符<>号>>]]></value>
</property>
<property name="age" value="123">
</property>
</bean>
2.2.6、注入外部Bean
ref属性 , 通过需要注入的Bean的id
注入
<bean id="uerService" class="com.flzj.service.UerService">
<property name="userDao" ref="userDaoImpl"></property>
</bean>
<bean id="userDaoImpl" class="com.flzj.dao.UserDaoImpl"></bean>
2.2.7、注入内部Bean
<bean>
标签嵌套进<propertiy>
标签罢了😇
<bean id="emp" class="com.flzj.bean.Emp">
<property name="ename" value="aa"></property>
<property name="gender" value="f"></property>
<property name="dept">
<bean id="dept" class="com.flzj.bean.Dept">
<property name="dname" value="研发部"></property>
</bean>
</property>
</bean>
2.2.8、级联赋值
<bean id="emp" class="com.flzj.bean.Emp">
<property name="ename" value="aa"></property>
<property name="gender" value="f"></property>
<!--级联赋值-->
<property name="dept" ref="dept"></property>
</bean>
<bean id="dept" class="com.flzj.bean.Dept">
<property name="dname" value="研发部"></property>
</bean>
需要Bean
有对应的get()
方法
<bean id="emp" class="com.flzj.bean.Emp">
<property name="ename" value="aa"></property>
<property name="gender" value="f"></property>
<!--级联赋值-->
<property name="dept" ref="dept"></property>
<property name="dept.dname" value="销售部"></property>
</bean>
<bean id="dept" class="com.flzj.bean.Dept">
<property name="dname" value="研发部"></property>
</bean>
2.2.9、注入集合
<array>标签和<value>标签
<property name="courses">
<array>
<value>java</value>
<value>c++</value>
<value>php</value>
</array>
</property>
<list>标签和<value>标签
<property name="list">
<list>
<value>L1</value>
<value>L2</value>
<value>L3</value>
</list>
</property>
<map>标签、<entry>标签 key
和 value
属性
<property name="map">
<map>
<entry key="k1" value="v1"></entry>
<entry key="k2" value="v2"></entry>
<entry key="k3" value="v3"></entry>
</map>
</property>
<set>标签和<value>标签
<property name="set">
<set>
<value>s1</value>
<value>s2</value>
<value>s3</value>
</set>
</property>
2.3.0 XML自动装配
<bean>标签的autowire属性
byName
根据属性名称注入 ,注入Bean 的 id 值 和 类属性名称一样
byType
根据属性类型注入
<bean id="emp" class="com.flzj.bean.Emp" autowire="byName">
<!-- <property name="dept" ref="dept"></property> -->
</bean>
<bean id="dept" class="com.flzj.bean.Dept"></bean>
3、工厂Bean
Spring有两种类型的Bean,一种普通Bean
,另一种FactoryBean
FactoryBean : 在配置文件定义Bean类型可以和返回类型不一样
需要
1、实现FactoryBean
接口
2、定义返回的bean
类型
public class MyBean implements FactoryBean<Course> {
@Override
public Course getObject() throws Exception {
Course course = new Course();
course.setCname("java");
return course;
}
@Override
public Class<?> getObjectType() {
return null;
}
@Override
public boolean isSingleton() {
return FactoryBean.super.isSingleton();
}
}
<bean id="myBean" class="com.flzj.bean.MyBean">
@Test
public void test1(){
ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Course course = classPathXmlApplicationContext.getBean("myBean", Course.class); // myBean类返回Course类
System.out.println(course);
}
4、Bean的作用域
在Spring中,Bean对象默认
是单例对象
scope属性用于设置单例还是多例
singleton
单例
prototype
多例
<bean id="myBean" class="com.flzj.bean.MyBean" scope="prototype"></bean>
5、Bean的生命周期
加入Bean的后置处理器
后,生命周期有七步
1、通过构造器创建Bean实例(无参数构造)
2、为Bean的属性设置值和对其他Bean引用(调用set方法)
3、把Bean实例传递Bean后置处理器的方法postProcessBeforeInitialization
.
4、调用Bean的初始化的方法(需要进行配置初始化的方法)
5、把Bean实例传递Bean后置处理器的方法postProcessAfterInitialization
6、Bean可以使用了(对象获取到了)
7、当容器关闭时候,调用Bean的销毁的方法(需要进行配置销毁的方法)
需要
实现BeanPostProcessor
接口,创建后置处理器
public class MyBeanPost implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("在初始化之前执行");
return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("在初始化之后执行");
return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
}
}
public class Orders {
public Orders() {
System.out.println("1、无参构造器创建Bean实例");
}
private String oname;
public void setOname(String oname) {
this.oname = oname;
System.out.println("2、调用set方法设置属性值");
}
public void initMethod(){
System.out.println("3、执行初始化方法");
}
public void destroyMethod(){
System.out.println("5、执行销毁方法");
}
}
<bean id="orders" class="com.flzj.bean.Orders"
init-method="initMethod" destroy-method="destroyMethod"
scope="singleton">
<property name="oname" value="TNT"></property>
</bean>
<!-- 配置后置处理器 -->
<bean id="beanPost" class="com.flzj.bean.MyBeanPost"></bean>
测试
@Test
public void test1(){
ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Orders orders = classPathXmlApplicationContext.getBean("orders", Orders.class);
System.out.println("4、获取Bean的实例对象");
// 手动销毁
((ClassPathXmlApplicationContext)classPathXmlApplicationContext).close();
}
1、无参构造器创建Bean实例
2、调用set方法设置属性值
在初始化之前执行
3、执行初始化方法
在初始化之后执行
4、获取Bean的实例对象
5、执行销毁方法
6、引入外部属性文件
引入德鲁伊线程池
properties
文件
prop.driverClass=com.mysql.jdbc.Driver
prop.url=jdbc:mysql://localhost:3306/userDb
prop.userName=root
prop.password=root
使用context
名称空间
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context/spring-context.xsd
">
<!--引入外部属性文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--配置连接池-->
<!-- 配置连接池 -->
<!-- DruidDataSource dataSource = new DruidDataSource(); -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<!-- dataSource.setDriverClassName("com.mysql.jdbc.Driver");
set方法注入
-->
<!-- 获取properties文件内容,根据key获取,使用spring表达式获取 -->
<property name="driverClassName" 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>
</beans>
基于注解方式
1.1、Bean管理
@注解名称(属性名称=属性值,属性名称=属性值…)
注解 | 作用 |
---|---|
@Component | 普通的 |
@Service | Service层 |
@Contoller | Web层 |
@Repository | Dao层 |
需要
1、导入jar包
2、开启组件扫描
<context:component-scan>标签
<context:component-scan base-package="com.flzj"></context:component-scan>
3、创建类,在类上面添加创建对象注解
@Component(value="")注解
@Component(value = "userService") // 等价<bean id="userSerivece" class="..."></bean>
public class UerService {
.....
use-default-filters
属性先设置为 false
inclue-filter
/ exclude-filter
: 包含 / 不包含
// 扫描那些内容
<context:component-scan base-package="com.flzj"
use-default-filters="false">
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
// 不扫描哪些内容太
<context:component-scan base-package="com.flzj"
use-default-filters="false">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
1.2、属性注入
注解 | 作用 |
---|---|
@Autowired | 根据属性类型自动装配 |
@Qualifier(value=) | 根据名称进行注入 |
@Resource(name=) | 可以根据类型注入,可以根据名称注入 |
@Value(value=) | 注入普通属性 |
1.3、完全注解开发
注解 | 作用 |
---|---|
@Configuration | 作为配置类,代替XML文件 |
@ComponentScan(basePackages=) | 组件扫描 |