Spring初始
什么是Spring
Spring是一个轻量级框架,解决了逻辑层和其他层的耦合问题,是IOC(控制反转)和AOP(面向切面)容器框架框架
IOC和AOP是Spring框架的两大核心
Spring体系结构
核心容器模块:核心容器模块(Spring Croe)提供了Spring框架基本功能主要组件时BeanFactory他是工厂模式的实现。
Spring上下文模式(Spring Context):Spring上下文模式是一个配置文件,向Spring框架提供上下文信息
面向切面编程模块(Spring AOP):面向切面编程模块提供了一个符合AOP要求的面向切面的编程实现途径,允许定义方法拦截器和切入点,将代码按照功能进行分离,以便干净解耦。
JDBC和DAO模块(Spring DAO):JDBC和DAO模块抽象层提供了有意义说的异常层次结构,可用该结构来管理异常处理和不同数据库提供商抛出的错误消息。
对象实体映射模块(Spring ORM):对象实体映射模块(Spring ORM)为流行的对象关系映射API提供集成层包括JPA和Hibernate。
Web模块(Spring Web):Web模块提供了基本的Web开发集成功能,如文件上传功能
MVC模块(Spring Web MVC):MVC模块(Spring Web MVC)建立在Spring核心功能之上,拥有Spring框架所有特性。
常使用标签基本属性:
ApplicationContext | 是Spring IOC容器的实现和代表它主要负责实例化配置和组装Bean |
---|---|
ClassPathXmlApplicationContext(“.xml文件的路径”) | 根据项目路径的XML配置实例化Spring容器 (注意当.xml文件在src下面的时候直接文件路径直接是xml文件若xml文件在包下面则要加包名即:包名/.xml文件) |
getBean | 获取Bean对象 |
1.通过类来获取bean 例:getBean(类型.class) | |
getBean 有三种形式获取Bean对象 | 2.通过Bean的名字或id来获取Bean 例:getBean(”.xml中Bean的名字或id“) |
3.通过名字+类名 例:getBean(“Beam的名字或id”,对应类.class) | |
constructor-arg | 用来对类的构造方法注入的(它是被Bean包围的) |
constructor-arg属性值有 index=“序号从0开始” | 0取得构造方法的第一个类型,1取得构造方法第二类型以此类推 |
constructor-arg属性值有 name=“构造其中的变量名” | 例如:constructor-arg name=“ID” |
constructor-arg属性值有 value | value一般配合前两个中的一个使用为变量符值 |
constructor-arg属性值有 ref=“另外一个Bean类型” | 如果参数值为非基本数据类型,则可通过ref为参数注入值,其值为另一个bean标签id或name属性的属性值 |
import | 可导入其他Spring的xml配置文件格式: |
Spring框架中依赖注入技术
Spring常用的两种注入1.构造方法注入和属性注入
- 构造注入
构造注入主要依赖构造方法实现
简单属性的构造方法的注入
public interface dao {
public String getStuInfo(Student student);
}
public class daoImpl implements dao{
//String.format()用于格式化方法,即用来控制字符串和变量的显示效果。
@Override
public String getStuInfo(Student student) {
String msString = String.format("学生学号:%s 学生的年龄:%s" + " 学生姓名:%s",
student.getStuID(), student.getStuAge(), student.getStuName());
return msString;
}
}
public interface Service {
public void showInfo(Student student);
}
public class serviceImpl implements Service {
private dao dao1;
public serviceImpl(dao dao1) {
this.dao1 = dao1;
}
@Override
public void showInfo(Student student) {
String msString =dao1.getStuInfo(student);
System.out.println(msString);
}
}
public class Student {
private String StuID;
private String StuName;
private String StuAge;
//使用构造方法进行注入必须有构造方法
public Student(String stuID, String stuName, String stuAge) {
StuID = stuID;
StuName = stuName;
StuAge = stuAge;
}
//由于是私有的必须有get()和set()方法
public String getStuID() {
return StuID;
}
public void setStuID(String stuID) {
StuID = stuID;
}
public String getStuName() {
return StuName;
}
public void setStuName(String stuName) {
StuName = stuName;
}
public String getStuAge() {
return StuAge;
}
public void setStuAge(String stuAge) {
StuAge = stuAge;
}
}
xml模块
<bean class="q.Student" id="student2">
<constructor-arg index="0" value="123455"/>
<constructor-arg index="1" value="张三"/>
<constructor-arg index="2" value="20"/>
</bean>
<bean class="q.daoImpl" id="dao"></bean>
<bean class="q.serviceImpl" id="service">
<constructor-arg index="0" ref="dao"/>
</bean>
测试类
//@Test – 使用该注解标注的public void方法会表示为一个测试方法
@Test
public void test1(){
ApplicationContext app=new ClassPathXmlApplicationContext("q/appli.xml");
Student s=(Student) app.getBean("student2");
serviceImpl sImpl= (serviceImpl) app.getBean("service");
sImpl.showInfo(s);
}
运行结果
学生学号:123455 学生的年龄:20 学生姓名:张三
setter简单注入
public interface Schooldao {
void er(A a);
}
public class A {
/*使用构造器注入*/
private int id;
private String name;
private int gonhao;//工号
private Student5 Studen;//类型为Student5
//用setter方法注入就不需要构造方法
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getGonhao() {
return gonhao;
}
public void setGonhao(int gonhao) {
this.gonhao = gonhao;
}
public Student5 getStuden() {
return Studen;
}
public void setStuden(Student5 studen) {
Studen = studen;
}
}
public class School implements Schooldao {
private A guan;
public A getGuan() {
return guan;
}
public void setGuan(A guan) {
this.guan = guan;
}
@Override
public void er(A a){
System.out.println("id= "+a.getId()+" Name " +a.getName()+
" gonhao "+a.getGonhao()+" Student5 "+a.getStuden());
}
}
public class Student5 {
private String xuehao;
private String name;
private String banji;
private String years;
@Override
public String toString() {
return "Student5{" +
"xuehao='" + xuehao + '\'' +
", name='" + name + '\'' +
", banji='" + banji + '\'' +
", years='" + years + '\'' +
'}';
}
public String getXuehao() {
return xuehao;
}
public void setXuehao(String xuehao) {
this.xuehao = xuehao;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getBanji() {
return banji;
}
public void setBanji(String banji) {
this.banji = banji;
}
public String getYears() {
return years;
}
public void setYears(String years) {
this.years = years;
}
}
public class test {
// @Before表示在任意使用@Test注解标注的public void方法执行之前执行
ApplicationContext IOC;
@Before
public void test1(){
IOC=new ClassPathXmlApplicationContext("Sater/ba.xml");
}
//@Test – 使用该注解标注的public void方法会表示为一个测试方法
@Test
public void test2(){
A a= (A) IOC.getBean("a2");
Schooldao school= (Schooldao) IOC.getBean("school2");
school.er(a);
}
}
xml配置(一定要配置在Beans里-)
<bean class="Sater.A" id="a2">
<property name="id" value="1234"/>
<property name="name" value="张三"/>
<property name="gonhao" value="122345"/>
<property name="studen" ref="studen"/>
</bean>
<bean class="Sater.Student5" id="studen">
<property name="xuehao" value="1234567"/>
<property name="name" value="李四"/>
<property name="banji" value="234"/>
<property name="years" value="4004"/>
</bean>
<!--autowire="byType" 自动注入-->
<bean class="Sater.School" id="school2" >
<property name="guan" ref="a2"/>
</bean>
运行结果
id= 1234 Name 张三 gonhao 122345 Student5 Student5{xuehao='1234567', name='李四', banji='234', years='4004'}
复杂类型注入
复杂类型注入用构造器注入和用Setter注入其实差不多
普通注入:
<property name="setxxxx" value="值" setxxx对应着set方法/>
bean注入:<property name="setxxxx" ref=bean />
数组注入:<property name="setxxxx"> <list><value></value></list></property>
list注入:<property name="setxxxx"> <list><value>值</value></list></property>
map注入:<property name="setxxxx"> <map><entry key=" key的值" Value="V的值"></entry></map></property>
set注入:<property name="setxxxx"> <set><value>值</value></set></property>
property注入:
例:<property name="setxxxx"> <props><prop key="aaaa">aaaaaa</prop></props></property>
使用P空间简化基于setter属性注入XML配置
例:<bean class=“bao名/类” id=“名字” p:要注入的类型=“XXXX” p:要注入的类型=“XXXX” >
使用C命名空间简化基于构造注入的XML的配置
例:C:要注入的类型=“XXXX” C:要注入的类型=“XXXX”
基于复杂类型的构造注入(可以好好康康可以特别关注xml文件最好自己敲一遍)例:
public interface Schooldao {
void er(A a,F fu);
}
//简单类型注入
public class A {
/*使用构造器注入*/
private int id;
private String name;
private int gonhao;
private Student5 Studen;
private List banlist;
private Map chanyingMap;
public void As() {
System.out.println("A类加载");
}
public A(int id, String name, int gonhao, Student5 studen, List banlist, Map chanyingMap) {
this.id = id;
this.name = name;
this.gonhao = gonhao;
this.Studen = studen;
this.banlist = banlist;
this.chanyingMap = chanyingMap;
}
public List getBanlist() {
return banlist;
}
public void setBanlist(List banlist) {
this.banlist = banlist;
}
public Map getChanyingMap() {
return chanyingMap;
}
public void setChanyingMap(Map chanyingMap) {
this.chanyingMap = chanyingMap;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getGonhao() {
return gonhao;
}
public void setGonhao(int gonhao) {
this.gonhao = gonhao;
}
public Student5 getStuden() {
return Studen;
}
public void setStuden(Student5 studen) {
Studen = studen;
}
}
//复杂类型
public class F {
private List<Student5> liststudent5;
private Map<Fm,Student5> fmStudent5Map;
public void F() {
System.out.println("F类加载");
}
public F(List<Student5> liststudent5, Map<Fm, Student5> fmStudent5Map) {
this.liststudent5 = liststudent5;
this.fmStudent5Map = fmStudent5Map;
}
public List<Student5> getListstudent5() {
return liststudent5;
}
public void setListstudent5(List<Student5> liststudent5) {
this.liststudent5 = liststudent5;
}
public Map<Fm, Student5> getFmStudent5Map() {
return fmStudent5Map;
}
public void setFmStudent5Map(Map<Fm, Student5> fmStudent5Map) {
this.fmStudent5Map = fmStudent5Map;
}
}
public class Fm {
private int id;
private String name;
public void Fm() {
System.out.println("Fm类进行加载");
}
public void Fm1() {
System.out.println("Fm1类进行加载");
}
@Override
public String toString() {
return "Fm{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Fm(int id, String name) {
this.id = id;
this.name = name;
}
}
public class Student5 {
private String xuehao;
private String name;
private String banji;
private String years;
public void Student5() {
System.out.println("Student5类进行加载");
}
public void Student52() {
System.out.println("Student52类进行加载");
}
@Override
public String toString() {
return "xuehao='" + xuehao + '\'' +
", name='" + name + '\'' +
", banji='" + banji + '\'' +
", years='" + years + '\'' +
'}';
}
public Student5(String xuehao, String name, String banji, String years) {
this.xuehao = xuehao;
this.name = name;
this.banji = banji;
this.years = years;
}
public String getXuehao() {
return xuehao;
}
public void setXuehao(String xuehao) {
this.xuehao = xuehao;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getBanji() {
return banji;
}
public void setBanji(String banji) {
this.banji = banji;
}
public String getYears() {
return years;
}
public void setYears(String years) {
this.years = years;
}
}
public class School implements Schooldao{
private A guan;
private F fu;
public A getGuan() {
return guan;
}
public void setGuan(A guan) {
this.guan = guan;
}
public F getFu() {
return fu;
}
public void setFu(F fu) {
this.fu = fu;
}
// public School(A guan , F fu){
// this.guan=guan;
// }
public void School() {
System.out.println("School类进行加载");
}
public <T> void mylist(T a, List suden){
for (Object object:suden){
T student5=(T)object;
System.out.println(student5.toString());
}
}
public void mymap( Map map){
for (Object key:map.keySet()){
System.out.println(key.toString()+" : "+map.get(key).toString());
}
}
@Override
public void er(A a,F fu){
System.out.println("A的属性输出");
String sd=String.format("姓名: "+a.getName()+" ID "+a.getId()+" 工号: " +a.getGonhao()
+" 学生 "+a.getStuden());
System.out.println(sd);
System.out.println("A的属性中的list");
mylist(a,a.getBanlist());
System.out.println("A的属性中的map");
mymap(a.getChanyingMap());
System.out.println("-------------------------------------------");
System.out.println("F的属性");
System.out.println("list");
mylist(fu,fu.getListstudent5());
System.out.println("map");
mymap(fu.getFmStudent5Map());
}
}
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class test {
ApplicationContext IOC;
@Before
public void test1(){
IOC=new ClassPathXmlApplicationContext("de/ab.xml");
}
@Test
public void test2(){
A a= (A) IOC.getBean("a");
F fu=(F)IOC.getBean("f");
Schooldao school= (Schooldao) IOC.getBean("school");
school.er(a,fu);
a.setId(444444);
school.er(a,fu);
//school.er(a);
}
}
xml文件
<!--depends-on:用来bean加载顺序当一个bean想让另一个bean在它之前加载可以设置depends-on=“另外一个bean”
lazy-init:懒加载这个lazy-init为true时在使用的时候才加载该bean
scope="singleton(默认的-单例)/prototype(多例)"
singleton和prototype区别:
singleton:同一个id只加载一次有线程安全风险
prototype:每一次使用都会创建一个bean-->
<!-- autowire="byName/bytype/constructor"
byName : 根据类型自动匹配,当出现多个类型或匹配不到类型就会报错
bytype : 根据set方法名字去自动匹配
constructor : 根据构造器匹配 优先根据名字匹配若没有匹配到会根据参数类型匹配
(构造器里面的参数进行匹配)名字没有匹配会根据类型匹配若类型出现
多个会注入失败但不会报错,将会默认调用参数构造函数
当类型不匹配时可以使用以下几种方法解决
1.设置某一个bean为主要bean:primary="true"
2.设置不需要自动注入的Bean :autowire-candidate="false"(忽略某自动注入)-->
<bean class="de.A" id="a" depends-on="student52" lazy-init="true" scope="prototype" init-method="As" autowire="constructor" >
<constructor-arg name="id" value="1"/>
<constructor-arg name="name" value="李四"/>
<constructor-arg name="gonhao" value="12345"/>
<!--<constructor-arg name="studen" ref="studen5"/>-->
<constructor-arg name="banlist" >
<list>
<value>张三</value>
<value>李四</value>
<value>王五</value>
</list>
</constructor-arg>
<constructor-arg name="chanyingMap" >
<map>
<entry key="21" value="都是"> </entry>
<entry key="4355" value="地方发"></entry>
<entry key="54" value="给v人TV发"></entry>
</map>
</constructor-arg>
</bean>
<bean class="de.F" id="f" init-method="F" >
<constructor-arg name="liststudent5" >
<list>
<ref bean="student52"></ref>
<ref bean="studen5"></ref>
</list>
</constructor-arg>
<constructor-arg name="fmStudent5Map">
<map>
<entry key-ref="fm" value-ref="studen5"/>
<entry key-ref="fm1" value-ref="student52"/>
</map>
</constructor-arg>
</bean>
<bean class="de.Fm" id="fm1" init-method="Fm1" primary="true">
<constructor-arg name="id" value="435"/>
<constructor-arg name="name" value="展示柜"/>
</bean>
<bean class="de.Fm" id="fm" init-method="Fm">
<constructor-arg name="id" value="435"/>
<constructor-arg name="name" value="展示柜"/>
</bean>
<bean class="de.Student5" id="studen5" init-method="Student5" primary="true">
<constructor-arg index="0" value="123456"/>
<constructor-arg index="1" value="张三"/>
<constructor-arg index="2" value="3班"/>
<constructor-arg index="3" value="2003"/>
</bean>
<bean class="de.Student5" id="student52" init-method="Student52">
<constructor-arg name="xuehao" value="2345"/>
<constructor-arg name="name" value="弟弟"/>
<constructor-arg name="banji" value="435"/>
<constructor-arg name="years" value="40001"/>
</bean>
<bean class="de.Student5" id="student523" >
<constructor-arg name="xuehao" value="2345"/>
<constructor-arg name="name" value="否等"/>
<constructor-arg name="banji" value="435"/>
<constructor-arg name="years" value="40001"/>
</bean>
//使用自动注入( autowire="byName")所以把bean中内容注销了
<bean class="de.School" id="school" init-method="School" autowire="byName">
<!--<constructor-arg index="0" ref="a"></constructor-arg>
<constructor-arg index="1" ref="f"></constructor-arg>-->
</bean>
运行结果
Student52类进行加载
Student5类进行加载
Fm类进行加载
Fm1类进行加载
F类加载
School类进行加载
A类加载
A的属性输出
姓名: 李四 ID 1 工号: 12345 学生 xuehao='123456', name='张三', banji='3班', years='2003'}
A的属性中的list
张三
李四
王五
A的属性中的map
21 : 都是
4355 : 地方发
54 : 给v人TV发
-------------------------------------------
F的属性
list
xuehao='2345', name='弟弟', banji='435', years='40001'}
xuehao='123456', name='张三', banji='3班', years='2003'}
map
Fm{id=435, name='展示柜'} : xuehao='123456', name='张三', banji='3班', years='2003'}
Fm{id=435, name='展示柜'} : xuehao='2345', name='弟弟', banji='435', years='40001'}
A的属性输出
姓名: 李四 ID 444444 工号: 12345 学生 xuehao='123456', name='张三', banji='3班', years='2003'}
A的属性中的list
张三
李四
王五
A的属性中的map
21 : 都是
4355 : 地方发
54 : 给v人TV发
-------------------------------------------
F的属性
list
xuehao='2345', name='弟弟', banji='435', years='40001'}
xuehao='123456', name='张三', banji='3班', years='2003'}
map
Fm{id=435, name='展示柜'} : xuehao='123456', name='张三', banji='3班', years='2003'}
Fm{id=435, name='展示柜'} : xuehao='2345', name='弟弟', banji='435', years='40001'}