Spring介绍,IOC(控制反转),DI(依赖注入)介绍及两种注入方法
第一中方法:在xml文件中注入:
(1)开源的轻量级的应用开发框架
特点:a.简化开发;b.解耦;c.集成;
原理对象与对象之间的依赖关系需要通过new的方式进行,在Spring中通过配置文件配置,只需要从配置文件中调用就好了
2.Spring容器:
(1)容器是什么?
可以将Spring容器看作是一个工厂。
(2)如何启动Spring容器
第一步:将jar包拷贝到WEB-INF的lib包下
第二步:将applicationContext.xml文件(配置文件)放到src下,文件名字可以更改
第三步:写一个java类。
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
(3)javabean
实现序列化Serializable接口
不带参数的构造器
属性及对应的get/set方法
3.Spring容器如何管理javabean
(1)如何实例化javabean
方式一:用构造器来实例化
第1步:
在applicationContext.xml文件中,有id(自定义)指定Bean的名称,class告诉Spring到哪个类中找(包名加上类名)
注意:一个类(HelloBean)必须要有一个无参的构造器。
第2步:
在java的测试类中
//获取applicationContext.xml,启动Spring容器
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//HelloBean.class是约束类型替代了强转,获取的Object类,getBean方法通过id拿到这个类(HelloBean)的对象,用着个替代了new HelloBean()
HelloBean helloBean =ac.getBean("helloBean",HelloBean.class);
Calendar c = ac.getBean("cal1" ,Calendar.class);
方式二:使用静态工厂实例化
注意:getInstance方法必须是一个静态方法。
方式三:使用实例工厂方法创建bean实例(了解)
(2)bean的命名
可以使用id或者name属性给bean命名
(3)bean的作用域
a.默认情况下,Spring容器对于每个bean只会创建一个实例。
xml文件中:id必须是唯一的
测试类中:
ApplicationContext ac = new ClassPathXmlApplicationContext("bean/applicationContext.xml");
SomeBean sb1 = ac.getBean("someBean1",SomeBean.class);
SomeBean sb2= ac.getBean("someBean1",SomeBean.class);
System.out.println(sb1==sb2);//true
b.可以通过设置scope属性值来指定bean的作用域:singleton(缺省值就是单例);prototype(原型):多个实例
xml文件中:
测试类中:
ApplicationContext ac = new ClassPathXmlApplicationContext("bean/applicationContext.xml");
SomeBean sb1 = ac.getBean("someBean1",SomeBean.class);
SomeBean sb2= ac.getBean("someBean1",SomeBean.class);
System.out.println(sb1==sb2);//true
c.在配置文件中添加了实体类中的方法,才能在java的测试类中调用这些方法(init和destory方法)
xml文件中:
测试类中:
AbstractApplicationContext ac = new ClassPathXmlApplicationContext("bean/applicationContext.xml");
SomeBean sb2 = ac.getBean("someBean2",SomeBean.class);
sb2.service();
ac.close();
(4)生命周期回调方法:(必须是单列的配置)
1.要关闭Spring容器必须使用ApplicationContext的子接口AbstractApplicationContext(只有它才有close方法),
init-method(初始化赋值);destroy-method(销毁方法);这两个方法在配置文件中直接配置
2.只有配置成(单例)的bean,在容器关闭的时候才会执行destory()销毁的方法
(5)延迟实例化:(了解)
Spring容器启动之后,会将所有的配置成单例的bean先实例化,就是Spring启动之后会先创建(new)好单列的那个类,自动调用无参的构造方法
怎样实现延迟创建类呢,在xml中加上lazy-init="true"
,
只用在调用了getBean方法的时候才会创建类,实例化
4.IOC
(1)IOC的概念(控制反转)
对象的依赖关系交给容器来管理。对象的依赖关系不去new,而是交给了容器,对成员变量的赋值也通过set注入完成
(2)DI的概念(依赖注入)
依赖注入的方法:容器可以通过调用对象的构造器或者set方法来建立对象之间的依赖关系。
(3)set方法注入(就是对类中成员变量在xml中通过set方法赋值)
a.提供一个不带参数的构造器。set注入会自动调用无参构造器创建一个类的实例,并通过set方法对成员变量赋值
b.必须有对应的set方法。
xml文件:
property:就是代表类中的所有成员变量;name:就是类的成员变量名,一定要一致,value:是对name属性就行赋值
Student类:
public class Student implements Serializable{
private Computer computer;
public Student(){
System.out.println("Student构造器");
}
public Computer getComputer() {
return computer;
}
public void setComputer(Computer computer) {
this.computer = computer;
}
public String toString(){
return "student的"+computer;
}
}
Computer类:
public class Computer implements Serializable{
private String name;
private String mainbord;
private String cup;
public Computer(){
System.out.println("Computer构造器");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMainbord() {
return mainbord;
}
public void setMainbord(String mainbord) {
this.mainbord = mainbord;
}
public String getCup() {
return cup;
}
public void setCup(String cup) {
this.cup = cup;
}
@Override
public String toString() {
return "Computer [cup=" + cup + ", mainbord=" + mainbord + ", name="
+ name + "]";
}
(4)构造器注入:直接调用类的有参构造器,并创建一个实例,对成员变量赋值;写了一个带参数的构造器也要加上一个无参的构造器
a.必须有一个带有参数的构造器,
在xml文件中:
construtor-arg:就是构造器中的成员变量;index:代表构造器中第几个成员变量,value:就是对成员变量赋值
在测试类中:
public void test1(){
//构造器注入
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//通过容器获得bean的实例
MobilePhone mp1= ac.getBean("mp1",MobilePhone.class);
System.out.println(mp1);
}
自我造的类MobilePhone
public class MobilePhone implements Serializable{
private String cpu;
private String ram;
//构造器注入必须具有有参的构造器
public MobilePhone(String cpu, String ram) {
super();
this.cpu = cpu;
this.ram = ram;
}
@Override
public String toString() {
return "MobilePhone [cpu=" + cpu + ", ram=" + ram + "]";
}
}
(5).自动装配(容易报错)
byName:容器会查找配置文件当中与属性名一致的bean,接下来,会调用set方法完成注入。
byType:容器会查找配置文件当中与属性类型一致的bean,接下来,会调用set方法完成注入。
constructor:容器会查找配置文件,与构造器当中的参数类型一致的bean,然后调用构造器完成注入。
autodetect:通过bean类来决定是使用constructor还是byType。
===============================================================================
1.构造器注入和set注入的参数(针对每个类中的参数制定相应的注入类型参数)
(1)普通参数注入(如上)int/String等
基本类型用:value
对象用:ref
集合用:list/set/map/props
(2)集合参数注入List/Set/Map/Properties
a。
python
hh
Tiger
b。特殊写法:把他们当作一个bean看待
java
武汉
Tiger
c。properties文件中的value值注入:固定的格式
d。Spring表达式作为参数注入
#{id.age}
#{id.card.id}
#{id.items[0]}
(2)集合参数注入List/Set/Map/Properties
自己造的类中:
public class MessageBean {
private List langs;
private Set cities;
private Mapscores;
private Properties dbinfo;
public Properties getDbinfo() {
return dbinfo;
}
public void setDbinfo(Properties dbinfo) {
this.dbinfo = dbinfo;
}
public Map getScores() {
return scores;
}
public void setScores(Map scores) {
this.scores = scores;
}
public List getLangs() {
return langs;
}
public void setLangs(List langs) {
this.langs = langs;
}
public Set getCities() {
return cities;
}
public void setCities(Set cities) {
this.cities = cities;
}
@Override
public String toString() {
return "MessageBean [cities=" + cities + ", dbinfo=" + dbinfo
+ ", langs=" + langs + ", scores=" + scores + "]";
}
在xml文件中(前提是类必须有set方法)
对list集合赋值
php
java
python
python
对set集合赋值
qwe
qwe
hh
对map集合赋值
对properti集合赋值
Tom
Tiger
(3)将集合看作是一bean进行配置。简化了上边的繁琐步骤,而且不需要写
java
C++
php
武汉
长沙
Tom
Tiger
(4)读取properties文件上的内容
(5)读取本文件中任意集合的value属性值:#{};ref就是通过id将其都拿过来
F
list用id名[0]
properties文件用id名.文中中的key
Map中用id名.key
嵌入层次多的就用id名.name.name
----------------------------------------------------------------------------------------------------------------------
第二种方法:在java类中用标注方式注入(一般优先使用)
A。在xml文中配置文件扫描类(固定格式)
B。在java类上边加上标注,与xml中的呼应
@Component(一般加上id):通用注解
@Component("stu")
public class Student implements Serializable{}
C。参数的注入方式
1)Setter注入推荐使用@Resource(只能处理set注入),该标注在使用的时候,建议使用name属性指定要注入的bean包下的id(类)。
@Resource(name="cp")
public void setComputer(Computer computer) {
this.computer = computer;
}
2).构造器注入推荐使用@Autowired
@Autowired
public Programmer(@Qualifier("cp")Computer computer){
this.computer=computer;
}
3)注入Spring表达式@Value(可以注入基本类型及String,可以注入Spring表达式,可以用在属性前面,可以用在对应的set方法前面)
a。@Value("TOM")
private String name;//直接赋值
b。通过properties文件赋值
前提是xml文件中得引入properties文件:
类中的属性
@Value("#{db.pagesize}")
private int pagesize;
案例:
Component:通用的注解
//告诉容器这个类的id进行命名sb,如果不写,bean的默认的id等于类名(首字母要小写)
@Component("sb")
//告诉容器更改作用域,改成不是单例的,默认是单列的
@Scope("prototype")
//告诉容器(单列的情况)延迟创建实例
@Lazy(true)
public class SomeBean implements Serializable{
public SomeBean(){
System.out.println("构造器被调用");
}
//告诉容器初始化
@PostConstruct
public void init(){
System.out.println("初始化调用");
}
//告诉容器销毁
@PreDestroy
public void destory(){
System.out.println("销毁调用");
}
}
xml文件中: