Spring-IOC(Inverse Of Control)控制反转。
IOC主要目的就是解耦。
Spring容器借助配置文档将相应的类实例化,进行注入构造器,属性和接口。
立即加载:立即加载就是表关联的时候,查询一个对象,会把他关联的对象都查出来初始化到属性中去,这个就是立即加载,所以在查询的时候可能出现多条查询语句
懒加载:懒加载在你进行数据库查询的时候,不会立即查询关联表的数据库,而是要等到你什么时候需要用到他里面的属性,必须要去查数据库的时候才会去查
懒加载在getBean才将bean加入内存,立即加载在ClassPathXmlApplicationContext就将全部的bean加入内存。
用类名的小写代表对象,比如说ChinesePeople类在契约式编程中chinesePeople作为对象。
BeanFactory是Spring最核心的框架提供了IOC配置机制
通过BeanFactory,启动IoC容器时,并不会再一一次初始化配置文件中定义的Bean,初始化动作发生在第一个调用时BeanFactory会缓存Bean实例,所以第二次使用getBean(),获取bean时将直接从IoC容器的缓存中获取Bean实例。
ApplicationContext是Spring的容器,是建立在BeanFactory基础上的提更了更多面向应用的功能。
BeanFactory和ApplicationContext的区别?
BeanFac tory在初始化容器时,并未实例化Bean,直到第一.次访问某个Bean时才实例目标Bean;
而ApplicationContext.则在初始化应用上下文时就实例化所有单实例的Bean,因此ApplicationContext的初始化时间稍长一些。
通过一个老师教学生课的例子来实践
Teacher接口:
public interface Teacher {
public void teach();
}
Bill类:
public class Bill implements Teacher {
public void teach() {
System.out.println("我来教课!");
}
}
Trade接口:
public interface Trade {
public void to();
}
JavaTrade类:
public class JavaTrade implements Trade {
private Teacher teacher;
public JavaTrade(Teacher teacher){
this.teacher=teacher;
}
public void to() {
this.teacher.teach();
}
}
常规使用方法:
缺点在于耦合度很高,Teacher和Trade紧紧耦合在一起。
public class Chairman {
public void go(){
Teacher tea=new Bill();
Trade trade=new JavaTrade(tea);//聚合 aggregation
trade.to();
}
public static void main(String[] args) {
new Chairman().go();
}
}
采用Spring容器的方法:
public class TestIOC2 {
public static void main(String[] args) {
// BeanFactory beanFactory=new ClassPathXmlApplicationContext("applicationContext1.xml");//懒加载
// JavaTrade j=beanFactory.getBean("java",JavaTrade.class);
// j.to();
ApplicationContext beanFactory=new ClassPathXmlApplicationContext("applicationContext1.xml");//立即加载
JavaTrade j=beanFactory.getBean("java",JavaTrade.class);
j.to();
}
}
xml配置文档:
<!--构造器注入-->
<beans>
<!--反射的方式将类反射成对象。-->
<bean id="bill" class="com.weikun.a.Bill">
</bean>
<bean id="java" class="com.weikun.a.JavaTrade">
<!--property:属性。下面这种方式必许有get、set。ref是指将bill对象送进teacher-->
<constructor-arg ref="bill"/>
<!-- 和上面是等效的 -->
<!-- <constructor-arg >-->
<!-- <ref bean="bill"/>-->
<!-- </constructor-arg>-->
</bean>
</beans>
Teacher接口:
public interface Teacher {
public void teach();
}
Bill类:
public class Bill implements Teacher {
public void teach() {
System.out.println("我来教课!");
}
}
Trade接口:
public interface Trade {
public void to();
}
JavaTrade类:
public class JavaTrade implements Trade {
private Teacher teacher;
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
public void to() {
this.teacher.teach();
}
}
传统方法:
public class Chairman {
public void go(){
Teacher tea=new Bill();
Trade trade=new JavaTrade();//聚合 aggregation
((JavaTrade) trade).setTeacher(tea);
trade.to();
}
public static void main(String[] args) {
new Chairman().go();
}
}
采用Spring容器方法
public class TestIOC1 {
public static void main(String[] args) {
BeanFactory factory=new ClassPathXmlApplicationContext("applicationContext.xml");
JavaTrade j=factory.getBean("java",JavaTrade.class);
j.to();
}
}
xml配置文档
<!--属性注入-->
<beans>
<!-- 反射的方式将类反射成对象。-->
<bean id="bill" class="com.ruigr.b.Bill">
</bean>
<bean id="java" class="com.ruigr.b.JavaTrade">
<!-- property:属性。下面这种方式必许有get、set。ref是指将bill对象送进teacher-->
<property name="teacher" ref="bill"/>
</bean>
</beans>
Axe接口:
public interface Axe {
public void chop();
}
SteelAxe类:
@Component
public class SteelAxe implements Axe {//契约式编程
public void chop() {
System.out.println("砍柴快!");
}
}
StoneAxe类:
@Component("myaxe")//<bead id="XXX"
public class StoneAxe implements Axe {
public void chop() {
System.out.println("砍柴慢!");
}
}
Person接口:
public interface Person {
//定义一个使用斧子的方法
public void useAxe();
}
Cinese类:
//默认是单例模式(getBean后是一个地址)singleton,也可改成原型模式(getBean后是多个地址)prototype
@Scope("singleton")
@Component
public class Chinese implements Person {
@Autowired//自动装配 替代了set、get
@Qualifier("steelAxe")//使用steelAxe
private Axe axe;
// public Axe getAxe() {
// return axe;
// }
// @Resource(name="myaxe")//默认使用myaxe
// public void setAxe(Axe axe) {
// this.axe = axe;
// }
public void useAxe() {
this.axe.chop();
}
}
测试类:
public class Test {
public static void main(String[] args) {
ApplicationContext ctx=new ClassPathXmlApplicationContext("com.weikun.c/beans2.xml");
Chinese c=ctx.getBean("chinese",Chinese.class);//契约式编程
System.out.println(c);
Chinese c1=ctx.getBean("chinese",Chinese.class);//契约式编程
System.out.println(c1);
SteelAxe steel=ctx.getBean("steelAxe",SteelAxe.class);
StoneAxe stone=ctx.getBean("myaxe",StoneAxe.class);
c.useAxe();
}
}
xml文档:
注解法采用很少的xml,该段xml文档的作用是限定范围
<context:component-scan base-package="com.ruigr.d">
<!--exclude满足正则表达式以Axe结尾的都屏蔽掉,默认是include-->
<!--<context:exclude-filter type="regex" expression=".*Axe"/>-->
</context:component-scan>