Spring是轻量级的IoC和AOP框架
SpringIoC是通过DI(dependency Injection)依赖注入的方式实现类与类之间的依赖关系的,以达到解耦的作用.
依赖方式:
一.基于xml文件的配置的注入:
*构造注入
*setter注入
*接口注入
针对于不同类型形参是怎么注入的呢?(常见POJO 对象注入DI)
setter方法
<bean id="userServiceSettersDI" class="com.mummy.spring.service.impl.UserService" destroy-method="close">
<property name="userDao" ref="userDao2"></property>
<property name="strValue" value="I Am String"></property>
<property name="listValue">
<list>
<value>list1</value>
<value>list2</value>
<value>list3</value>
</list>
</property>
<property name="setValue">
<set>
<value>set1</value>
<value>set2</value>
<value>set3</value>
<value>set4</value>
</set>
</property>
<property name="strArrayValue">
<list>
<value>strArray1</value>
<value>strArray2</value>
<value>strArray3</value>
<value>strArray4</value>
</list>
</property>
<property name="setValue">
<set>
<value>set1</value>
<value>set2</value>
<value>set3</value>
<value>set4</value>
</set>
</property>
<property name="mapValue">
<map>
<entry key="key1" value="1"></entry>
<entry key="key2" value="2"></entry>
<entry key="key3" value="3"></entry>
</<map>>
</property>
</bean>
2.scope属性:bean实例对象的scope作用域范围 “singleton/prototype”
singleton 仅仅初始化一次,创建一个实例A a = new A();
prototype 每次对bean的访问都会创建一个新的实例 A a0 = new A(); A a1 = new A();
<bean id="userDao2Prototype" class="com.mummy.spring.dao.impl.UserDao2" scope="prototype"></bean>
bean延迟加载(容器启动加载,还是实例化的时候加载呢?默认是在容器初始化的时候就加载好了,延迟加载时在实例化的时候才加载)
1.bean延迟加载的几种方式:lazy-init=”false|true”
默认方式:lazy-init="false"(容器加载的时候就实例化出所有被注册的beanClass)
lazy-init="true"
System.out.println("---容器已启动---");
ac.getBean("userAnOther");
//不使用lazy-init="true",报错cano'tLoadBeanClassException
//使用了lazy-init="true"
输出:---容器已启动---
此方式只有在实例化此beanClass的时候才报错cannotLoadBeanClassException
2.应用场景:当A类应用B类,A类就需要延迟加载;如果所有的bean都需要延迟加载,在头文件中写入:default-lazy-init=”true”
3.Spring容器会自动向bean中注入依赖–>自动装配(为什么要自动装配呢?减轻编程人员在applicatonContext.xml配置bean,还要指明依赖关系)
自动装配就是为了让我们不要指明依赖关系,而是通过属性的设置来达到相同的效果(属性备注为@Autowired)
在spring的配置文件applicationContext.xml的要被注册bean中加上一个属性:autowired="byName|byType|constructor"
byName和byType都是通过setter方法注入的
byName 定义被依赖的bean名称需要与类中对应的名称一致,就会匹配依赖关系
在service类中依赖具体Dao实现的对象;private IUserDao userDao; 在配置文件中被注册的背依赖类bean的id则必须为userDao;实际上就是省略了userDao的property属性<property name="userDao" ref="userDaoAutowired"/>
byType 通过定义的依赖bean的类型来进行匹配,依赖的对象可以是接口本身也可以是接口的实现
1.在配置文件中有多个接口的实现,他们也都可以通过byType注入到成员变量中去,容易报错:
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.mummy.spring.dao.IUserDaoAutowired] is defined: expected single matching bean but found 2: userDao,userDaoAutowire
2.两个同类型怎么解决呢?
在不想要被依赖的的bean上加上autowire-candidate="false":放弃候选
结论:建议不要在配置文件中使用自动装配,虽然可以减少配置文件,但是不利于维护
1.单个xml文件的读取:
读取配置文件;ApplicatonContext ac = new ClassPathXmlApplicatonContext("ApplicationContext-autowired.xml");
2.多个xml文件的读取:
ApplicatonContext ac = new ClassPathXmlApplicatonContext("ApplicationContext-autowired.xml","ApplicationContext.xml");
等价于:
String[] configFiles = new String[]{"ApplicationContext-autowired.xml","ApplicationContext.xml"};
ApplicatonContext ac = new ClassPathXmlApplicatonContext(configFiles);
3.用约定的方式(约定)
ApplicatonContext ac = new ClassPathXmlApplicatonContext("ApplicationContext*.xml");
4.读取一个总的配置文件,其他配置都被包含在这一个总配置文件中
ApplicatonContext ac = new ClassPathXmlApplicatonContext("ApplicationContext-all.xml");
ClassPathXmlApplicatonContext:是指在编译目录的根文件(去类的编译路径读取配置文件);如果是web项目,项目编译之后的所有的java文件都放在WEB-INF/classes/...下面,
5.文件系统读取 (实现不同)
ApplicationContext ac = new FileSystemXmlApplicationContexxt();
//源文件夹在window系统下会被转成普通文件夹
二.通过注解配置
DI的方式有三种:setter依赖,constructor依赖,interface依赖(少见)
通过set方法或构造方法进行依赖注入,必须在依赖类中提供被依赖类实例的setter方法和构造方法.
在Spring的配置文件中,注册好需要被管理的bean类,格式:>>
< bean id=”userDao” class=”com.mummy.spring.dao.UserDao” >< / bean >
上面这句话的意思就是在程序中创建一个实例;UserDao userDao = new UserDao();但是他的创建由Spring容器来管理创建
在需要依赖的bean中通过需要依赖的对象,进行注入即可,
例如:service依赖于userDao类的实例
(构造方法注入)
< bean id=”userService” class=”com.mummy.spring.service.UserService”>
< constructor-arg ref=”userDao”/>
< /bean>
setter方法注入
< bean id=”userService” class=”com.mummy.spring.service.UserService”>
< property name=”userDao” ref=”userDao”/>
< /bean>
setter方法注入的注意点,property中的name必须和依赖类中的set方法的后半部分相似,例如:setName() 则propery中的name则是name;setUid 则propery中的name则是uid;
好的编程风格应该是set后的成员变量名首字母大写,则property中的name直接比对成员变量的名称即可.成员变量正规的讲,应该是实例域
Spring针对于bean,他可以被指定为是延迟加载的
延迟加载是啥呢?
I:Spring是默认在容器启动时,就加载配置文件中被注册好的bean类的.(一启动容器,就创建好所有被注册的类的对象)
II:而延迟加载呢,是当容器启动的时候不去创建类的实例,等到需要被创建的时候才去创建.
III:这样做的优点就是节省内存资源(貌似现在内存也不贵了,哈哈哈)
IV:应用场景:当你的依赖类A在创建实例之前需要依赖于被依赖类B的实例,此时这个A就需要延迟加载,需要等B先实例化一个实例.
Spring针对bean属性scope,可以被指定为是singleton(单例)还是prototype(原型)
singleton是啥呢?
I:知道月亮吧,有且仅有一个,简略了解一下,下一篇单独讲一讲单例模式吧!
II:原型:相当于皇帝的老婆,千千万,各有各的特色.
由bean创建出来的实例都是同一个,怎么比较呢?
对象的相等性有两种方式:==和equals方法比较,==是会比较对象在内存中的hash值的,而equals则不会,只比较对象是否是同类型!
< bean id=”userDao” class=”com.mummy.spring.dao.UserDao” scope=”prototype”>< / bean >
bean默认是单例创建的