spring-1-spring介绍和IOC容器开发
一、介绍
1、版本
2、下载(jar包依赖)
下载
文件分配
maven添加jar包依赖
https://www.cnblogs.com/nwu-edu/p/9542074.html
注意:如果出错可能是因为没有logging日志包
3、入门案例
用spring的方式创建一个对象实例
package com.wang.Spring5;
public class User {
public void add(){
System.out.println("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">
<!--配置User对象创建-->
<!--这里创建了一个user的实例对象-->
<bean id="user" class="com.wang.Spring5.User"></bean>
</beans>
- 测试
@Test
public void testAdd(){
//1、加载配置文件
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
//2、获取配置创建的对象
//getBean()第一个参数为这个类的别名,第二个参数为返回类型
User user = context.getBean("user", User.class);
System.out.println(user);
user.add();
}
二、IOC容器
1、IOC底层原理
IOC是什么,能做什么,怎么做到的
2、IOC接口(BeanFactory)
3、IOC具体操作_Bean管理(基于xml)
什么是Bean管理:(两个操作)
1、Spring创建对象
2、Spring注入属性
(1)基于xml方式创建对象
<!--配置User对象创建-->
<!--这里的意思是给com.wang.Spring5.User起了一个别名-->
<bean id="user" class="com.wang.Spring5.User"></bean>
//1、在spring配置文件中,使用bean标签,标签里面添加对应属性,就可以实现对象创建
//2、在bean标签有很多属性,介绍常用的属性
*id属性:唯一标识(别名)
*class属性:类的全路径
*name属性:很少用,类似于id
//3、创建对象时,默认使用无参构造函数创建(没有的话就会报错)
(2)在java代码中获取xml中实现的对象
@Test
public void test$(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
UserService userService = context.getBean("userService", UserService.class);
userService.add();
}
(3)基于xml注入属性
DI:依赖注入(注入属性)(Dependency Insert)
IOC和DI的区别:DI是IOC的一种具体实现,是在创建了对象的基础上操作的
set注入(必须要有set方法、而且必须在创建了对象的基础上)
<bean id="book" class="com.wang.Spring5.Book">
<property name="bname" value="书名1"></property>
<property name="time" value="2001"></property>
</bean>
有参构造注入(注意:类中必须要有相应的构造函数)
<bean id="order" class="com.wang.Spring5.Order">
<constructor-arg name="oname" value="12"></constructor-arg>
<constructor-arg name="address" value="江西"></constructor-arg>
</bean>
——另一种方式(通过索引)
<bean id="order" class="com.wang.Spring5.Order">
<constructor-arg index="0" value="34"></constructor-arg>
<constructor-arg index="1" value="北京"></constructor-arg>
</bean>
set注入简化,使用p名称空间注入
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="book" class="com.wang.Spring5.Book" p:bname="jiu" p:time="无名氏"></bean>
注入特殊类型的数据(null,集合等)
-- 含null
<constructor-arg name="oname">
<null></null>
</constructor-arg>
-- 含<>符号
<constructor-arg name="address">
<value><![CDATA[<<北京>>]]></value>
</constructor-arg>
注入内部bean和级联赋值
可以理解为一个bean对象的属性指向另一个bean对象
1、创建service类和dao类
2、在service中调用dao里的方法
- 外部bean
<bean id="userService" class="com.wang.service.UserService">
<!--注入userDao对象
name属性:类里面属性名称
ref属性:创建userDao对象bean标签id
-->
<property name="userDao" ref="userDao"></property>
</bean>
<bean id="userDao" class="com.wang.dao.UserDaoImp"></bean>
- 内部bean:和上面那一种方法达到的效果是一样的
<bean id="emp" class="com.wang.company.Employee">
<property name="ename" value="wangwang"></property>
<property name="eage" value="18"></property>
<property name="dept">
<bean id="dept" class="com.wang.company.Department">
<property name="dname" value="安保部门"></property>
</bean>
</property>
</bean>
- 级联复制(一般不用)
<bean id="emp" class="com.wang.company.Employee">
<property name="eage" value="18"></property>
<property name="ename" value="wang"></property>
<property name="dept" ref="dept"></property>
<property name="dept.dname" value="人力资源部"></property>
</bean>
<bean id="dept" class="com.wang.company.Department"></bean>
注入集合类型属性
- 在对象里设置集合类型
public class Person {
//1.数组类型属性
private String[] array;
//2.list集合类型属性
private List<String> list;
//3.map集合类型属性
private Map<String, String> map;
//4.set集合类型属性
private Set<String> set;
}
<bean id="ryan" class="com.ryan.spring5.inputCollection.Person">
<!--数组类型属性注入-->
<property name="array">
<array>
<value>arr1</value>
<value>arr2</value>
</array>
</property>
<!--list类型属性注入-->
<property name="list">
<list>
<value>list1</value>
<value>list2</value>
</list>
</property>
<!--map类型属性注入-->
<property name="map">
<map>
<entry key="map-key1" value="map-value1"></entry>
<entry key="map-key2" value="map-value2"></entry>
</map>
</property>
<!--set类型属性注入-->
<property name="set">
<set>
<value>set1</value>
<value>set2</value>
</set>
</property>
</bean>
- 在集合里面设置对象类型值
理解:即处理下面这种数据,集合里面是示例对象的情况
private List<Family> familyList;
public void setFamilyList(List<Family> familyList) {
this.familyList = familyList;
}
操作:使用了ref标签里的bean属性
<bean>
<property name="familyList">
<list>
<ref bean="family"></ref>
<ref bean="family"></ref>
<ref bean="family"></ref>
</list>
</property>
</bean>
<bean id="family" class="com.wang.gather.Family">
<property name="f" value="13"></property>
</bean>
- 把集合注入部分提取出来
理解:即把下面这个部分独立出来,便于多次调用,有点类似于创建一个公用数组,这样大家都可以调用了
<property name="array">
<array>
<value>arr1</value>
<value>arr2</value>
<value>arr3</value>
</array>
</property>
操作
<!--这个地方类似于一个公开数组-->
<util:list id="list1">
<value>张辽</value>
<value>hello</value>
<value>太死</value>
</util:list>
<bean id="person" class="com.wang.gather.Person">
<property name="list" ref="list1"></property>
</bean>
4、bean管理
(1)工厂bean(Factory bean)
工厂bean的作用:用java代码来代替一些比较赋值比较麻烦的bean,通过在xml文件中配置我们的工厂bean,然后在工厂bean中实现返回配置好的我们需要的bean,然后我们接收这个bean时只需要引入这个工厂bean的id即可
Spring有两种类型的bean, 一种普通bean, 一种工厂bean(FactoryBean)
普通Bean: 在配置文件中定义的bean类型就是返回类型;
工厂bean: 在配置文件中定义的bean类型可以和返回类型不一样,
有点意思是传入一个参数得到另外一个参数
怎么创建Factorybean
- (1)创建类, 实现接口FactoryBean;
- (2) 实现接口里面的方法, 在实现的方法中定义返回的bean类型.
Mybean
package com.wang.Factorybean;
public class Mybean {
//只要一个名字
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Mybean{" +
"name='" + name + '\'' +
'}';
}
}
- MybeanImp
public class MybeanImp implements FactoryBean<Mybean> {
public Mybean getObject() throws Exception {
//在这个地方完成对mybean的配置
Mybean mybean = new Mybean();
mybean.setName("dashazi");
return mybean;
}
public Class<?> getObjectType() {
return null;
}
public boolean isSingleton() {
return false;
}
}
- xml文件
<!--注意创建的是工厂bean-->
<bean id="mybean" class="com.wang.Factorybean.MybeanImp"></bean>
- 实现
@Test
public void test7(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");
Mybean mybean = context.getBean("mybean", Mybean.class);
System.out.println(mybean);
}
(2)bean作用域(单例和多例)
单例就是所有的请求都用一个对象来处理,比如我们常用的service和dao层的对象通常都是单例的;
多例则指每个请求用一个新的对象来处理,比如action;
- 如何设置单例和多例
可以用Spring配置文件bean标签里面的scope属性, 来设置单实例/多实例.
Spring默认单实例, 即scope=singleton
可以通过设置scope=prototype来设置多实例
如:
<bean id="testBean" class="com.ryan.spring5.testScope.TestBean" scope="prototype"></bean>
这就是一个多例对象
singleton和prototype区别
- singleton单例,prototype多例
- 设置scope值是单例时,加载spring配置文件时就会创建单实例对象,而scope值时多例对象时,加载spring配置文件时不会创建对象,使用getbean方法时才会调用
另外还有:request(一次请求),session(一此对话),不做解释
(3)bean生命周期
- 具体步骤
- 通过构造器创建bean实例(无参数构造);
- 设置bean的属性值和对其他bean引用(调用set方法);
- *(可以不进行)**把bean实例传递给bean后置处理器的方法postProcessBeforeInitialization
- 调用bean的初始化的方法(需要配置初始化方法);
- *(可以不进行)**把bean实例传递给bean后置处理器的方法postProcessAfterInitialization
- bean可以使用了(获取到了对象);
- 当容器关闭的时候, 调用bean的销毁方法(需要配置销毁方法)
- 演示
public class Orders {
private String name;
public Orders() {
System.out.println("1、无参数构建");
}
public void setName(String name) {
this.name = name;
System.out.println("2、调用set方法");
}
public void add(){
System.out.println("6、获取到了对象");
}
//初始化方法,对应initMethod属性
public void initMethods(){
System.out.println("4、调用初始化方法");
}
//销毁方法,对应destroyMethod属性
public void destroyMethods(){
System.out.println("5、调用销毁方法");
}
}
public class MybeanPost implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("3、初始化前的操作");
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("5、初始化之后的操作");
return bean;
}
}
<bean id="orders" class="com.wang.Factorybean.Orders" init-method="initMethods" destroy-method="destroyMethods">
<property name="name" value="hello世家"></property>
</bean>
<!--后置处理器-->
<bean id="beanpost" class="com.wang.Factorybean.MybeanPost"></bean>
<!--注意点:后置处理器一旦在xml文件中实例化,所有的bean示例都会配置这个处理器-->
@Test
public void test8(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");
Orders orders = context.getBean("orders", Orders.class);
orders.add();
context.close();
}
(4)xml自动装配
自动装配: 根据指定装配规则(属性名称或属性类型), Spring自动将匹配的属性值进行注入
- 根据名字匹配
<!--原来的配置方式-->
<!-- <bean id="dep" class="com.wang.autowire.Dep"></bean>-->
<!-- <bean id="emp" class="com.wang.autowire.Emp">-->
<!-- <property name="dep" ref="dep"></property>-->
<!-- </bean>-->
<!--后来的配置方式-->
<bean id="emp" class="com.wang.autowire.Emp" autowire="byName"></bean>
<!--它会根据emp里的属性的名称自动匹配id也式同样名字的属性-->
<bean id="dep" class="com.wang.autowire.Dep"></bean>
- 根据类型匹配
注意点:一旦自动装配选择了bytype,那么我们需要的那个属性的类就只能创建一个实例
<bean id="emp" class="com.wang.autowire.Emp" autowire="byType"></bean>
<bean id="dep" class="com.wang.autowire.Dep"></bean>
(5)引入外部属性的文件
- 首先需要配置命名命名空间
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">
- 调用外部属性
prop.driverClass = com.mysql.jdbc.Driver
prop.url = jdbc:mysql://localhost:3306/userDB
prop.userName = root
prop.password = 123456
<!--引入外部文件配置数据库-->
<context:property-placeholder location="classpath:bean.properties"></context:property-placeholder>
<!--调用数据-->
<bean id="myjdbc" class="com.wang.jdbc.MyJdbc">
<property name="driverClass" 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>
5、IOC具体操作_Bean管理(基于注解)
注解是代码标记,格式:@注解名称(属性名称=属性值,属性名称=属性值)
使用注解配置的目的:简化xml配置
- spring针对bean对象管理有四个注解
- 注意的是这些注解的底层是一样的,只不过为了逻辑更加清晰
- @Component 用于普通组件
- @Service 用于业务逻辑层
- @Controller 用于web层
- @Repository 用于dao层
(1)注解管理基本操作
- 开启组件扫描:分两步: 引入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 http://www.springframework.org/schema/context/spring-context.xsd">
<!--开启组件扫描, 要扫描多个包则用逗号隔开-->
<context:component-scan base-package="com.wang.dao,com.wang.service"></context:component-scan>
</beans>
- 创建类调用注解
//这个等价于<bean id="userservice" class="全类名">
//可以默认不写:不写的话value值就是类的名称首字母小写
@Component(value = "userservice")
public class UserService {
public void add(){
System.out.println("add________________");
}
}
- 测试调用
@Test
public void test1(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean_1.xml");
UserService userservice = context.getBean("userservice", UserService.class);
System.out.println(userservice);
}
- 经过测试调用,发现事实上注解的作用就是把那个对应的类帮助我们在xml文件里简化了开发而已,并不是另起炉灶,所以我们获取实例对象仍然是在使用原来的方式获取
(2)扫描配置装置
可以令一些配置组件不被扫描,而另外一些配置组件扫描
- 只扫描部分组件
<context:component-scan base-package="com.wang.dao,com.wang.service" use-default-filters="false">
<!--设置只监听特定注解的内容-->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
- 设置不扫描部分组件
<context:component-scan base-package="com.wang.service,com.wang.dao" >
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
</context:component-scan>
(3)基于注解进行属性注入
属性注入的注解
- @Autowired: 根据属性类型进行自动装配
- @Qualifier: 根据属性名称进行注入
- @Resource: 可以根据类型注入, 可以根据名称注入
- @Value: 注入普通类型属性
@Autowired和@Qualifier注解
//先创建一个实例
@Component(value = "userDao")
public class UserDaoImp implements UserDao {
}
//在另外一个类中
@Component(value = "userservice")
public class UserService {
//这个会自动识别到我们在UserService中添加的注解,并添加到这个属性来
//这个时根据属性名称自动装配(必须要实例的名称一样才能注入)
@Autowired
//当找不到时就会去寻找教userdao的实例对象
@Qualifier(value = "userDao")
private UserDao userDao;
}
- @resource注解
//根据属性注入
@Resource
//根据名称注入
@Resource(name = "userService")
private UserDao userDao;
- @Value注解
@Value(value = "13")
private int age;
(4)完全注解开发
可以使用配置类代替配置文件, 从而使用纯注解来写代码(一般使用在SpringBoot中)
- 新建SpringConfig类并添加注解, 以代替原来的xml文件:
//作为配置类,替代xml配置文件
@Configuration
//扫描包的注解
@ComponentScan(basePackages = {"com.wang"})
//其他地方完全一致,但获取实例对象的地方变化了
public class springconfig {
}
- 改写测试程序
@Test
public void est2(){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(springconfig.class);
UserService userservice = context.getBean("userservice", UserService.class);
userservice.add();
}
spring-1-spring介绍和IOC容器开发的更多相关文章
- 【spring源码分析】IOC容器初始化(总结)
前言:在经过前面十二篇文章的分析,对bean的加载流程大致梳理清楚了.因为内容过多,因此需要进行一个小总结. 经过前面十二篇文章的漫长分析,终于将xml配置文件中的bean,转换成我们实际所需要的真正 ...
- 【spring源码分析】IOC容器初始化(十)
前言:前文[spring源码分析]IOC容器初始化(九)中分析了AbstractAutowireCapableBeanFactory#createBeanInstance方法中通过工厂方法创建bean ...
- 转 Spring源码剖析——核心IOC容器原理
Spring源码剖析——核心IOC容器原理 2016年08月05日 15:06:16 阅读数:8312 标签: spring源码ioc编程bean 更多 个人分类: Java https://blog ...
- 【spring源码分析】IOC容器初始化(二)
前言:在[spring源码分析]IOC容器初始化(一)文末中已经提出loadBeanDefinitions(DefaultListableBeanFactory)的重要性,本文将以此为切入点继续分析. ...
- 【spring源码分析】IOC容器初始化(三)
前言:在[spring源码分析]IOC容器初始化(二)中已经得到了XML配置文件的Document实例,下面分析bean的注册过程. XmlBeanDefinitionReader#registerB ...
- 【spring源码分析】IOC容器初始化(四)
前言:在[spring源码分析]IOC容器初始化(三)中已经分析了BeanDefinition注册之前的一些准备工作,下面将进入BeanDefinition注册的核心流程. //DefaultBean ...
- 【spring源码分析】IOC容器初始化(七)
前言:在[spring源码分析]IOC容器初始化(六)中分析了从单例缓存中加载bean对象,由于篇幅原因其核心函数 FactoryBeanRegistrySupport#getObjectFromFa ...
- 【spring源码分析】IOC容器初始化——查漏补缺(一)
前言:在[spring源码分析]IOC容器初始化(十一)中提到了初始化bean的三个步骤: 激活Aware方法. 后置处理器应用(before/after). 激活自定义的init方法. 这里我们就来 ...
- Spring源码分析专题 —— IOC容器启动过程(上篇)
声明 1.建议先阅读<Spring源码分析专题 -- 阅读指引> 2.强烈建议阅读过程中要参照调用过程图,每篇都有其对应的调用过程图 3.写文不易,转载请标明出处 前言 关于 IOC 容器 ...
随机推荐
- FreeSql使用WithSql+ ToSQL 查询数据
FreeSql是一个支持.NET Core 2.1+..NET Framework 4.0+ 以及 Xamarin的ORM(Object Relational Mapping)对象关系映射的组件 支持 ...
- 从实力的角度出发来思考这道AOP题目
文/楠木大叔 技术更迭,一往无前.技术人总是要不断学习以适应社会的发展和行业对我们的要求.每隔一段时间,就会有纷至沓来的新技术,新知识,新概念,我们应该如何应对,是被逼到墙角,还是主动出击? 导读 从 ...
- Atcoder rc122-c Calculator 斐波那契
传送门 题解 先说结论: 任意正整数可以拆分成若干个斐波那契数 斐波那契数列: 1 1 2 3 5 8 13 21 34 例 17 = 13 + 3 + 1 看上去是对的,怎么证明呢? 首先假如每一个 ...
- pytest xfail的使用
@pytest.mark.xfail: 期望测试用例是失败的,但是不会影响测试用例的的执行; 如果测试用例执行失败的则结果是xfail(不会额外显示出错误信息); 如果测试用例执行成功的则结果是xpa ...
- 【VBS】获取文件夹大小
文件截图: 运行结果: 第一步:编写脚本 GetFloderSize.vbs 1 '获得文件夹的大小 by 王牌飞行员(https://www.cnblogs.com/KMould/p/1233481 ...
- 由一次PasswordBox密码绑定引发的疑问 ---> WPF中的附加属性的定义,以及使用。
1,前几天学习一个项目的时候,遇到了PasswordBox这个控件,由于这个控件的Password属性,不是依赖属性,所以不能和ViewModel层进行数据绑定. 2,但是要实现前后端彻底的分离,就需 ...
- 你有一份经典SQL语句大全,请注意查收
一.基础部分 1.创建数据库 CREATE DATABASE dbname 2.删除数据库 DROP DATABASE dbname 3.创建新表 CREATE TABLE tabname(col1 ...
- StackOverflow上面 7个最好的Java答案
StackOverflow发展到目前,已经成为了全球开发者的金矿.它能够帮助我们找到在各个领域遇到的问题的最有用的解决方案,同时我们也会从中学习到很多新的东西.这篇文章是在我们审阅了StackOver ...
- 树上染色+可怜与超市(树状DP)
这两道题是学长精心准备的,想了很长时间,比较经典. 第一题 树上染色 有一棵点数为 N的树,树边有边权.给你一个在 0∼N之内的正整数 K,你要在这棵树中选择 K 个点,将其染成黑色,并将其他的 N− ...
- Windows下安装kubectl及Node和Pod操作常用命令
kubernetes通过kube-apiserver作为整个集群管理的入口.Apiserver是整个集群的主管理节点,用户通过Apiserver配置和组织集群,同时集群中各个节点同etcd存储的交互也 ...