Spring配置文件
【对 第一个 HelloWorld 程序】 进行解刨知识点
1.Bean标签基本配置
用于配置对象交由Spring 来创建。 默认情况下它调用的是类中的无参构造函数,如果没有无参构造函数则不能创建成功。【这种方法叫做 无参方法实例化 Bean对象是根据它的无参构造来获取的】
基本属性: id:Bean实例在Spring容器中的唯一标识 【emm 唯一标识 真是个常识.】
class:Bean的全限定名称 【记得带包名 而且方法要有无参构造】
2.Bean标签范围配置
除了 Id 和 Class ,Bean标签还有一个属性 scope : 学过JSP都知道 是域、范围的意思.
scope:指对象的作用范围,取值如下:
取值范围 |
说明 |
singleton |
默认值,单例的 |
prototype |
多例的 |
request |
WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 request 域中 |
session |
WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 session 域中 |
global session |
WEB 项目中,应用在 Portlet 环境,如果没有 Portlet 环境那么globalSession相当于 session |
所以 我们没配置 他就会 singleton 单的,我们先详说 singletion 和 prototype :
因为其他设计到了 WEB 项目:
Bean标签范围配置
1)当scope的取值为singleton时 Bean的实例化个数:1个 【无参构造 只执行一次】
Bean的实例化时机:当Spring核心文件被加载时,实例化配置的Bean实例 【意思是说 emmmm 在获取到XML对象时 只执行一次无参构造 那么证明只实例化一次 以后都是同一对象 而且 只有一个Bean对象 因为是singleton 单例 】
Bean的生命周期: 对象创建:当应用加载,创建容器时,对象就被创建了 【出生】
对象运行:只要容器在,对象一直活着 【活着】
对象销毁:当应用卸载,销毁容器时,对象就被销毁了 【销毁】
2)当scope的取值为prototype时 Bean的实例化个数:多个 【实例化一个 就执行一次无参构造】
Bean的实例化时机:当调用getBean()方法时实例化Bean 【意思是说 emmmm 在获取到XML对象时 不会实例化 当 getBean 时 会执行无参构造一次 每一次都是不同的对象 不同的Bean】
对象创建:当使用对象时,创建新的对象实例
对象运行:只要对象在使用中,就一直活着
对象销毁:当对象长时间不用时,被 Java 的垃圾回收器回收了
例: 【Junit 测试:】
HelloServer.java : 【接口】
package com.bihu.helloDao; public interface HelloService { void show(); }
HelloServiceImpl.java : 【实现类】
package com.bihu.helloImpl; import com.bihu.helloDao.HelloService; public class HelloServiceImpl implements HelloService { //无参构造: public HelloServiceImpl() { System.out.println("实例化了一个 HelloServiceImpl 对象 执行了无参构造"); } public void show() { System.out.println("Hello World!"); } }
applicationContext.xml:
<?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 默认 singleton【单例】 自行更换 prototype【多例】 --> <bean id="hello_bean" class="com.bihu.helloImpl.HelloServiceImpl" scope="singleton" ></bean> </beans>
Test: 【一般测试类 都新建一个文件夹 Test 然后里面包都和 main 的差不多 其实就是 一个 java 一个 resource 】
import com.bihu.helloImpl.HelloServiceImpl; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class test { @Test //要导入 Junit 的 GAV public void springTest(){ //获取XML ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml"); //实例化两个 HelloServiceImpl 对象: HelloServiceImpl app1 = (HelloServiceImpl)app.getBean("hello_bean"); HelloServiceImpl app2 = (HelloServiceImpl)app.getBean("hello_bean"); //分别打印他的地址 如果在你spring配置文件中的Bean 是singleton 的话 地址会一样,如果是prototype的话 会不一样 其次执行的无参构造次数也不一样 // 所以可以根据它的特性来DEBUG: System.out.println(app1); System.out.println(app2); } }
所以 单例 和 多例的区别 就在这里 自己测试即可.
3. Bean生命周期配置
init-method:指定类中的初始化方法名称
destroy-method:指定类中销毁方法名称
直接在 Bean 中配 即可 ,但是确保 Bean中有函数存在,例:
当然名字你自己设置啊 自定义.
HelloServiceImpl.java
package com.bihu.helloImpl; import com.bihu.helloDao.HelloService; public class HelloServiceImpl implements HelloService { //无参构造: public HelloServiceImpl() { System.out.println("实例化了一个 HelloServiceImpl 对象 执行了无参构造"); } public void show() { System.out.println("Hello World!"); } /*--初始化 和 销毁 方法: --*/ public void init() { System.out.println("Bean出生了"); } public void destroy() { System.out.println("Bean销毁了"); } }
Spring配置文件:
<?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 默认 singleton【单例】 自行更换 prototype【多例】 --> <bean id="hello_bean" class="com.bihu.helloImpl.HelloServiceImpl" scope="singleton" init-method="init" destroy-method="destroy" ></bean> </beans>
测试: 当你单单获取xml 的话 他会执行 init方法 因为在spring中设置了
import com.bihu.helloImpl.HelloServiceImpl; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class test { @Test //要导入 Junit 的 GAV public void springTest(){ ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml"); } }
它的输出:
信息: Loading XML bean definitions from class path resource [applicationContext.xml] 实例化了一个 HelloServiceImpl 对象 执行了无参构造 Bean出生了 Process finished with exit code 0
但是 没执行销毁方法 因为 emmmm 没来得及打印....
如果你实在想去测试,那么:
import com.bihu.helloImpl.HelloServiceImpl; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class test { @Test //要导入 Junit 的 GAV public void springTest(){ //ApplicationContext 改成了 ClassPathXmlApplicationContext,因为ClassPathXmlApplicationContext是ApplicationContext的实现类,所以有close方法. ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml"); app.close(); //关掉 所以就可以自动调用 销毁方法了 //这个理解即可 知道那个原理 } }
输出:
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@574caa3f: startup date [Fri Jun 18 11:57:00 CST 2021]; root of context hierarchy 六月 18, 2021 11:57:00 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions 信息: Loading XML bean definitions from class path resource [applicationContext.xml] 实例化了一个 HelloServiceImpl 对象 执行了无参构造 Bean出生了 六月 18, 2021 11:57:00 上午 org.springframework.context.support.AbstractApplicationContext doClose 信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@574caa3f: startup date [Fri Jun 18 11:57:00 CST 2021]; root of context hierarchy Bean销毁了
4.Bean实例化三种方式
1.无参构造方法实例化
2.工厂静态方法实例化
3.工厂实例方法实例化
第一种不多说 上面那个就是 无参构造方法实例化
工厂静态方法实例化:
说到工厂 就想起 factory ,就想到工厂模式,而且是静态的:
其实就是 返回一个指定的对象回去(工厂) ,然后在Spring配置文件中配置【Class变为 工厂模式的地址 、 添加 factory-method 字段,值是工厂类的方法【返回对象那个方法】】
其实就是反射,接下来看代码:
先创建一个静态工厂 这里是 StaticFactroy类:
package com.bihu.factroy; import com.bihu.helloImpl.HelloServiceImpl; //静态工厂 public class StaticFactroy { public static HelloServiceImpl GetHelloServiceImpl(){ return new HelloServiceImpl(); } }
然后我们配置Spring文件:
<?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--静态工厂实例化:--> <bean id="StaticFactory" class="com.bihu.factroy.StaticFactroy" factory-method="GetHelloServiceImpl"></bean> </beans>
记住 静态工厂实例化模式是factory-method 一个就够!!!
然后我们测试:Test.java:
<?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--静态工厂实例化:--> <bean id="StaticFactory" class="com.bihu.factroy.StaticFactroy" factory-method="GetHelloServiceImpl"></bean> </beans>
输出:
信息: Loading XML bean definitions from class path resource [applicationContext.xml] 实例化了一个 HelloServiceImpl 对象 执行了无参构造 Hello World! Process finished with exit code 0
证明是 毫无问题的 这种。
工厂实例方法实例化
刚刚是静态的 这次来个不是静态的:
想想看 既然是工厂实例方法 少不了创建工厂模式,但是由于不是静态的话 肯定要先获取到他的工厂实例 然后配置哪方面: 肯定要先有工厂Bean 那么就是 先创建一个工厂Bean 然后跟着这个工厂Bean进去找方法即可 完成实例化 Bean.
其中 在Spring的配置文件中 获取 工厂Bean 是:factory-bean 属性,值是 自己配的 工厂Bean,所以工厂Bean 相当于Class 。
所以大体思路 唯一要改的就是 Spring的配置文件 和 去掉静态方法 上代码:
package com.bihu.factroy; import com.bihu.helloImpl.HelloServiceImpl; //工厂模式实例化 public class StaticFactroy { public HelloServiceImpl GetHelloServiceImpl(){ return new HelloServiceImpl(); } }
去掉静态的啊 因为是工厂实例方法实例化...有点绕口..
然后是Spring 配置文件:
<?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--工厂实例化:--> <!-- 因为不是静态的 所以先创建一个FactoryBean,在通过FactoryBean去反射找到指定的方法 实例化 Bean --> <!-- 先获取工厂Bean: --> <bean id="FactoryBean" class="com.bihu.factroy.StaticFactroy"></bean> <!-- 然后根据工厂Bean获取指定方法获取Bean --> <bean id="Bean" factory-bean="FactoryBean" factory-method="GetHelloServiceImpl" ></bean> </beans>
其实这里的 FactoryBean 相当于 静态工厂模式的 Class .
说那么多 已经是很保姆级别的了 请带脑子阅读...
测试: Test.java :
import com.bihu.helloImpl.HelloServiceImpl; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class test { @Test //要导入 Junit 的 GAV public void springTest(){ ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml"); HelloServiceImpl staticFactory = (HelloServiceImpl)app.getBean("Bean"); staticFactory.show(); } }
Bean 差不多了... 主要还是要有反射思维...
注意: 不要看这里的包名 我乱打的!!! 和MVC模式对不上的!不是MVC模式!!! 你只需知道 一个接口 一个实现即可,因为是测试 所以没认真看包名.你只需要知道 那个是接口 那个是实现即可,真正的MVC模式命名和归类是很规范的.
完.