小白初写Spring核心容器功能
Spring核心容器功能
1.spring优点 方便解耦,简化开发 AOP编程的支持 申明式事务的支持 方便程序的测试等等
一,Spring模块架构图
- core container : 核心容器,是spring框架的基石,任何spring项目运行时都会生成一个容器,把项目运行时需要的对象全部管理起来。创建对象,销毁对象,对象关系的依赖。
- test : 测试,可以与junit-4整合起来,测试容器中某些对象。
- AOP : 面向切面编程,可以无耦合的给很多方法进行功能的增强。
- data access : 数据访问,提供了jdbc模板,可以对数据库进行操作。还可以与其它的ORM框架,如hibernate进行整合使用。
- transactions : 事务, spring提供了声明式事务功能,只需要对事务功能进行一次配置,就可以在所有的方法上增加事务。
- web - struts : spring的web模块可以和struts框架整合起来使用。
- web - mvc : spring开发了自己的一个控制层框架,叫做SpringMVC,代替struts2框架,从开发速度,运行效率上都比struts2要好。
二 Spring核心的两个概念
spring的第一大特性IOC
Inversion Of Controller 控制反转
把创建对象的权利反转交给了spring,这一过程就叫做控制反转
在spring中加载对象,就是通过反射加载
讲个笑话:
什么是IOC? 就是通过反射加载对象的过程
什么是反射? mysql的驱动连接就是通过反射来加载的.
作者:将达吉恩
来源:****
原文:https://blog.****.net/weixin_39836604/article/details/79249684
版权声明:本文为博主原创文章,转载请附上博文链接!
- IOC : 控制反转,也叫DI,叫依赖注入。
控制反转:以前对象都是由程序员自己创建管理的,现在由Spring框架的容器来管理所有的对象。(容器本身也是对象)
依赖注入:假如Student对象内部有个Clazz属性,就说明学生依赖一个班级。
把一个clazz对象装入student对象中,这个操作叫注入。spring框架的容器会自动完成依赖注入。 - AOP:面向切面(方面)编程。
解决日志记录,性能统计,安全控制,事务管理功能。共同特点是都要给很多个方法增强功能,增强的功能代码是重复性的。AOP就可以写一遍代码,给所有的方法增强功能。 OOP:面向对象编程。AOP是对OOP的一个补充。
三 内容及方式
1.Spring框架是管理对象的(core container)。
2.Spring框架中管理的对象叫做bean.(
Spring以bean的方式组织和管理Java中的各个组件和关系。
Spring容器通过单例设计模式和工厂设计模式还有反射来加载获取类对象。)
3.在Spring中加载对象就是通过反射加载。
加载对象的三种方式
第一种:通过默认构造器。
无参构造方法创建bean:
<bean id="student" class="com.youzhong.entity.Student"/>
使用上面的标签配置bean时,容器调用无参构造方法。
有参构造方法创建bean:
<bean id="student" class="com.youzhong.entity.Student">
<!-- constructor-arg配置构造方法参数 -->
<!-- index设置参数的索引,value设置参数的值 -->
<!-- <constructor-arg index="0" value="20"/> -->
<!-- name设置参数名 -->
<!-- <constructor-arg name="id" value="30"/> -->
<!-- type设置参数的类型,ref是引用容器中的另一个bean的唯一标识 -->
<constructor-arg index="0" value="40"/>
<constructor-arg index="1" type="java.lang.String" value="张三"/>
<constructor-arg index="2" ref="student2"/>
</bean>
<bean id="student2" class="com.youzhong.entity.Student"/>
第二种:使用静态工厂来创建对象,需要创建静态工厂类。
我想要电脑:
方式一:硬盘+主板+内存条+显示器+键盘+鼠标+CPU
方式二:Thinkpad电脑
电脑类:
public class Computer {
private String cpu;
private String disk;
private String memory;
private String board;
private String keyboard;
private String mouse;
静态电脑工厂:
/**
* 静态电脑工厂
* @author Administrator
*
*/
public class ComputerFactory {
//生产电脑
//静态方法
public static Computer createComputer() {
return new Computer("core-i7","500GB机械","4GB","昂达","机械键盘","雷蛇");
}
}
配置spring.xml
<!-- factory-method配置工厂里面的静态方法 -->
<bean id="computer" class="com.youzhong.factory.ComputerFactory" factory-method="createComputer"/>
第三种:通过实例工厂来创建对象,可以在实例工厂初始化对象之前加一些自己的其他操作。
实例工厂创建(了解)
指工厂里创建对象的方法是普通方法,非static的,只能用对象调用。
实例工厂:
/**
1. 实例电脑工厂
2. @author Administrator
3. */
public class ComputerFactory {
public ComputerFactory() {
System.out.println("***********");
}
//生产电脑
//普通方法
public Computer createComputer() {
return new Computer("core-i7","500GB机械","4GB","昂达","机械键盘","雷蛇");
}
}
配置spring.xml
<!-- 1、创建工厂bean -->
<bean id="factory" class="com.youzhong.factory.ComputerFactory"/>
<!-- 2、创建computer -->
<!-- factory-bean引用工厂对象 -->
<bean id="computer" factory-bean="factory" factory-method="createComputer"/>
四.Spring核心容器给对象注入的三种方式
1.构造方法注入(有参构造)
public class Student {
private int id;
private String name;
private String sex;
public Student(int id, String name, String sex) {
super();
this.id = id;
this.name = name;
this.sex = sex;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", sex=" + sex + "]";
}
}
配置spring.xml
<bean id="student" class="com.youzhong.entity.Student">
<constructor-arg index="0" value="66"/>
<constructor-arg index="1" value="张梓"/>
<constructor-arg index="2" value="男"/>
</bean>
测试类
public static void main(String[] args) {
//1、解析spring.xml,创建核心容器
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
//2、从容器中取出student
Object bean = ac.getBean("student");
System.out.println(bean);
}
2.set方法注入(最常用)
public class Student {
private int id;
private String name;
private String sex;
public void setDd(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", sex=" + sex + "]";
}
}
配置spring.xml
<bean id="student" class="com.youzhong.entity.Student">
<!-- property标签使用set方法注入,name需要和set方法名匹配 -->
<property name="dd" value="88"/>
<property name="name" value="张梓"/>
<property name="sex" value="男"/>
</bean>
测试
public static void main(String[] args) {
//1、解析spring.xml,创建核心容器
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
//2、从容器中取出student
Object bean = ac.getBean("student");
System.out.println(bean);
}
可以注入复杂的类型
public class Student {
private int id;
private String name;
private String sex;
private Student girlFriend;//女朋友
private Student[] boyFriends;//男朋友们
private List<String> laoxiang;//老乡们
private Set<String> sheyou;//舍友们
private Map<String,Double> money;//存款
private Properties chengji;//成绩
配置spring.xml
<bean id="student" class="com.youzhong.entity.Student">
<!-- property标签使用set方法注入,name需要和set方法名匹配 -->
<property name="id" value="88"/>
<property name="name" value="张梓"/>
<property name="sex" value="男"/>
<property name="girlFriend" ref="s2"/>
<property name="boyFriends">
<array>
<ref bean="s3"/>
<ref bean="s4"/>
</array>
</property>
<property name="laoxiang">
<list>
<value>张三</value>
<value>张三丰</value>
</list>
</property>
<property name="sheyou">
<set>
<value>王龙</value>
<value>王龙</value>
<value>小胖</value>
</set>
</property>
<property name="money">
<map>
<entry key="ICBC" value="200.1"/>
<entry key="ABC" value="1200.1"/>
<entry key="CBC" value="3200.1"/>
</map>
</property>
<property name="chengji">
<props>
<prop key="java基础">90</prop>
<prop key="struts2">60</prop>
<prop key="spring">30</prop>
</props>
</property>
</bean>
<bean id="s2" class="com.youzhong.entity.Student">
<property name="name" value="刘瑶"/>
</bean>
<bean id="s3" class="com.youzhong.entity.Student">
<property name="name" value="杨语"/>
</bean>
<bean id="s4" class="com.youzhong.entity.Student">
<property name="name" value="康子硕"/>
</bean>
3.注解注入(很常用)
@Autowired 自动绑定
@Resource 资源
上面两个注解可以添加在属性上面,如果添加了此注解,容器必须为此属性注入,容器会找一个bean进行赋值,如果找不到就直接报错。
注解注入一般用在对象类型的属性上,不在int,String等基本类型上使用。
注意:注解注入需要添加spring-aop.jar包,配置注解开关。
球队Team类
public class Team {
private int id;
private String name;
@Override
public String toString() {
return "Team [id=" + id + ", name=" + name + "]";
}
}
球员Player类
public class Player {
private int id;
private String name;
//@Resource
@Autowired
private Team team;
@Override
public String toString() {
return "Player [id=" + id + ", name=" + name + ", team=" + team + "]";
}
}
配置spring.xml
<!-- 注解开关:扫描@Autowired等注解 -->
<context:annotation-config/>
<bean id="player" class="com.youzhong.entity.Player"/>
<bean id="team" class="com.youzhong.entity.Team"/>
测试
public static void main(String[] args) {
//1、解析spring.xml,创建核心容器
ApplicationContext ac = new ClassPathXmlApplicationContext("spring2.xml");
//2、从容器中取出student
Object bean = ac.getBean("player");
System.out.println(bean);
}
@Autowired与@Resource的区别:
1、@Autowired是spring框架提供的注解,@Resource是jdk提供的注解。
2、@Autowired根据类型绑定
@Resource先根据名字绑定,再根据类型绑定。
五.Spring核心容器的其他功能
一、bean的作用域(scope):
常用的两个作用域:singleton 单例的 , prototype 原型的(多例的)
单例:容器只创建一个实例。
多例:容器会创建多个实例。
默认创建的bean是单例的。
1、单例bean的配置:
<bean id="shanzhu" class="com.youzhong.entity.ShanZhu"/>
<bean id="shanzhu" class="com.youzhong.entity.ShanZhu" scope="singleton"/>
2、多例的bean配置:
<bean id="shanzhu" class="com.youzhong.entity.ShanZhu" scope="prototype"/>
二、注解扫描管理bean
有4个注解可以扫描管理bean:
@Controller , @Service , @Repository , @Component
控制器 服务,业务 仓库,存储 组件
上面4个注解是加在类上的。
1、在spring.xml中配置注解扫描的包
<!-- 组件扫描,bask-package配置基包,扫描基包及其所有子包中的类 -->
<context:component-scan base-package="com.youzhong.entity"/>
2、在类上添加注解
@Controller
public class ShanZhu {
}
注解扫描管理bean时,创建的bean的默认id是类名小驼峰。
3、测试
public static void main(String[] args) {
//1、解析spring.xml,创建核心容器
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
//2、从容器中取出student
Object bean = ac.getBean("shanzhu");
System.out.println(bean);
}
注意:
1.注解扫描创建的bean,作用域(scope)默认是单例的。
注解扫描创建多例的bean,需要添加一个注解:
@Component
@Scope("prototype")
public class Banana {
}
- 注解扫描管理的bean,默认id是类名小驼峰。
也可以自定义bean的id:
@Component("orange")
@Scope("prototype")
public class Banana {
}
- @Component(“orange”)
上面注解的配置,"orange"默认赋给了注解的value属性,注解必须有value属性。
@Table(name="t_user")
name=是不能省略的,如果省略,"t_user"默认赋给value属性,@Table没有value属性。
如果要给注解赋多个属性值,属性名都不能省略。
三、bean的生命周期
1、Apple类
public class Apple {
//初始化
public void aaaa() {
System.out.println("先洗洗");
}
//销毁
public void destroy() {
System.out.println("扔到垃圾桶");
}
}
2、配置spring.xml
<!-- init-method配置初始化方法,destroy-method配置销毁方法 -->
<bean id="apple" class="com.youzhong.entity.Apple"
init-method="aaaa" destroy-method="destroy"
/>
3、测试
public static void main(String[] args) {
//1、解析spring.xml,创建核心容器
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
//2、从容器中取出student
//Object bean1 = ac.getBean("apple");
//关闭容器
ac.close();
}
小知识: 核心容器会在创建出来bean之后,立即对其初始化,调用init-method配置的方法。
当容器销毁时,也会销毁所有的bean,之前会调用destroy-method配置的方法。
一般的bean不会管理生命周期,复杂的bean才会管理生命周期。
四、懒加载
核心容器会立即把单例的bean创建出来,多例的bean不会立即创建。
懒加载是对于单例的bean进行设置的。
复杂的bean,可能用不到的bean,才需要懒加载。
五、depends-on 依赖
比如容器创建两个bean,apple和banana
<bean id="banana" class="com.youzhong.entity.Banana"/>
六、autowire 自动绑定
autowire使用byName或byType自动绑定时,需要调用set方法。
1、开发Player,Team类
> public class Player {
> private String name;
private Team team;
public void setTeam(Team team) {
this.team = team;
}
@Override
public String toString() {
return "Player [name=" + name + ", team=" + team + "]";
}
}
public class Team {
}
2、配置spring.xml
<!-- autowire叫做自动绑定byName是根据名字byType是根据类型 -->
<bean id="player" class="com.youzhong.entity.Player" autowire="byName"/>
<bean id="xxx" class="com.youzhong.entity.Team"/>
3、测试
public static void main(String[] args) {
//1、解析spring.xml,创建核心容器
```
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
```
Object bean = ac.getBean("player");
System.out.println(bean);
}
autowire配置default时,会使用根标签<beans>中的default-autowire的设置。
<!-- autowire叫做自动绑定byName是根据名字byType是根据类型 -->
<bean id="player" class="com.youzhong.entity.Player" autowire="default"/>
<bean id="xxx" class="com.youzhong.entity.Team"/>
七、多个spring.xml互相导入
还可以使用如下方式解析多个配置文件
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml","spring2.xml");
ApplicationContext ac = new ClassPathXmlApplicationContext("spring*.xml");
八、核心容器接口
常用的接口有两个:BeanFactory , ApplicationContext
BeanFactory是spring框架内部使用的,只提供了管理bean的功能。
ApplicationContext 是框架外部使用的,它是BeanFactory的孙子接口,扩展了BeanFactory的功能,增加了一些企业级的应用。
Player bean = ac.getBean(“player”, Player.class); // 可以返回准确类型的bean