一.Spring当中Bean的延迟加载
所有的bean默认情况下都是非延迟加载的,即所有的bean都是在加载Spring容器的时候完成bean对象的创建,即执行
ApplicationContext ac=new ClassPathXmlApplicationContext("bean.xml")
的时候完成bean对象的创建,我们getBean的时候直接从容器中去拿这个Bean就可以了,是否延迟加载由lazy-init来控制,默认是false,如果变成true就在getBean的时候去创建bean对象
<?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-3.2.xsd">
<!-- 设置延迟加载 -->
<bean id="st" class="com.csii.factory.FactoryDemo" factory-method="jdbc" lazy-init="true">
</bean>
</beans>
二.Bean的作用域及生命周期
package com.csii.service.impl;
public class ServiceTest {
public void init() {
System.out.println("初始化..........");
}
public void hello() {
System.out.println("hello............");
}
public void destory() {
System.out.println("销毁...........");
}
}
<?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-3.2.xsd">
<bean id="servicetest" class="com.csii.service.impl.ServiceTest" init-method="init" destroy-method="destory"></bean>
</beans>
package com.csii.test;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.csii.dao.impl.JDBCTestImpl;
import com.csii.service.impl.ServiceTest;
class Test1 {
ApplicationContext ac=new ClassPathXmlApplicationContext("bean2.xml");
@Test
void test1() {
ServiceTest st=(ServiceTest) ac.getBean("servicetest");
//使用ApplicationContext的子类AbstractApplicationContext ,因为他有close方法
AbstractApplicationContext applicationContext= (AbstractApplicationContext) ac;
st.hello();
applicationContext.close();
}
}
十月 26, 2018 10:03:33 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [bean1.xml]
初始化..........
hello............
十月 26, 2018 10:03:33 下午 org.springframework.context.support.AbstractApplicationContext doClose
信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@7a765367: startup date [Fri Oct 26 22:03:32 CST 2018]; root of context hierarchy
销毁...........
Init方法和destroy
Init是bean被创建的时候被调用,主要做一些准备工作
Destroy是bean被销毁的时候被调用,做清理工作
Bean的生命周期和容器一致,容器被创建bean就被创建,容器销毁bean就被销毁
关闭Spring容器的时候需要用到ApplicationContext的子类AbstarctApplicationContext的close
三.Spring的构造器注入
package com.csii.dao;
public interface UserDao {
public void say();
}
package com.csii.dao.impl;
import com.csii.dao.UserDao;
import com.csii.service.impl.ServiceTest;
public class UserDaoImpl implements UserDao {
private ServiceTest serviceTest;
@Override
public void say() {
// TODO Auto-generated method stub
System.out.println("say.........");
}
}
向ServiceTest当中注入UserDao对象
package com.csii.service.impl;
import com.csii.dao.UserDao;
public class ServiceTest {
private UserDao userdao;
public ServiceTest(UserDao userdao) {
super();
this.userdao = userdao;
}
public void hello() {
System.out.println("hello............");
userdao.say();
}
}
<?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-3.2.xsd">
<bean id="servicetest" class="com.csii.service.impl.ServiceTest">
<!--
index:构造方法的参数的索引顺序
type:构造方法的参数的类型(不是必须 的)
value:值
-->
<constructor-arg index="0" ref="userdao"></constructor-arg>
</bean>
<bean id="userdao" class="com.csii.dao.impl.UserDaoImpl"></bean>
</beans>
package com.csii.test;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.csii.service.impl.ServiceTest;
class Test1 {
ApplicationContext ac=new ClassPathXmlApplicationContext("bean1.xml");
@Test
void test() {
ServiceTest st=(ServiceTest) ac.getBean("servicetest");
st.hello();
}
}
十月 27, 2018 11:21:21 上午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@7a765367: startup date [Sat Oct 27 11:21:21 CST 2018]; root of context hierarchy
十月 27, 2018 11:21:22 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [bean1.xml]
hello............
say.........
需要注意的是,当写<constructor-arg index="0" ref="userdao"></constructor-arg>的type属性值的时候,它指的是构造器当中其对应的数据类型,比如此处的是UserDao,如果写他的实现类UserDaoImpl会报错。如果不写的话,会自动去构造器当中查找对象的类。
type:此处在有参构造器当中是UserDao接口,故type也要是是UserDao接口,不要指定实现类UserDaoImpl,否则一定会报错
四.Spring的外部注入
package com.csii.service.impl;
import com.csii.dao.UserDao;
public class ServiceTest {
private UserDao userdao;
public void setUserdao(UserDao userdao) {
this.userdao = userdao;
}
public void hello() {
System.out.println("hello............");
userdao.say();
}
}
<?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-3.2.xsd">
<!-- 外部bean的方式注入 -->
<bean id="service" class="com.csii.service.impl.ServiceTest">
<property name="userdao" ref="userdao"></property>
</bean>
<bean id="userdao" class="com.csii.dao.impl.UserDaoImpl"></bean>
</beans>
package com.csii.test;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.csii.service.impl.ServiceTest;
class Test1 {
ApplicationContext ac=new ClassPathXmlApplicationContext("bean1.xml");
@Test
void test() {
ServiceTest st=(ServiceTest) ac.getBean("service");
st.hello();
}
}
十月 27, 2018 2:46:20 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@7a765367: startup date [Sat Oct 27 14:46:20 CST 2018]; root of context hierarchy
十月 27, 2018 2:46:20 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [bean1.xml]
hello............
say.........
总结:外部注入的方式,也是通过默认的构造器然后进行的set设置然进行注入的,外部bean的方式注入,必须提供要注入的bean的set方法
五.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-3.2.xsd">
<!-- 外部bean的方式注入 -->
<bean id="service" class="com.csii.service.impl.ServiceTest">
<property name="userdao">
<bean class="com.csii.dao.impl.UserDaoImpl"></bean>
</property>
</bean>
</beans>
bean的内部注入方式的缺点是,内部的bean不能被其他的bean引用,这是不合理的