Ioc
- 代码的依赖关系被Ioc集中管理起来,清晰明了
- 每个类只需要关心自己的业务逻辑
- 修改依赖关系很容易
通过一个Ioc容器感受一下什么是IoC
package car;
public interface Car {
public void start();
public void turnLeft();
public void turnRight();
public void stop();
}
package car;
public class Audi implements Car{
@Override
public void start() {
System.out.println("Audi start");
}
@Override
public void turnLeft() {
System.out.println("Audi turnLeft");
}
@Override
public void turnRight() {
System.out.println("Audi turnRight");
}
@Override
public void stop() {
System.out.println("Audi stop");
}
}
package car;
public class Buick implements Car{
@Override
public void start() {
System.out.println("Buick start");
}
@Override
public void turnLeft() {
System.out.println("Buick turnLeft");
}
@Override
public void turnRight() {
System.out.println("Buick turnRight");
}
@Override
public void stop() {
System.out.println("Buick stop");
}
}
package humen;
public interface Humen {
public void goHome();
}
package humen;
import car.Car;
public abstract class HumenWithCar implements Humen {
protected Car car;
public HumenWithCar (Car car) {
this.car = car;
}
public abstract void goHome();
}
package humen;
import car.Car;
public class ZhangSan extends HumenWithCar{
public ZhangSan(Car car){
super(car);
}
@Override
public void goHome() {
car.start();
car.turnLeft();
car.turnRight();
car.stop();
}
}
package humen;
import car.Car;
public class LiSi extends HumenWithCar{
public LiSi (Car car){
super(car);
}
@Override
public void goHome() {
car.start();
car.stop();
}
}
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/*
实例化bean
保存bean
提供bean
每一个bean要产生一个唯一的id与之对应
* */
public class IocContainer {
private Map<String , Object> beans = new ConcurrentHashMap<>();
/*
根据BeanId获取Bean
*/
public Object getBean(String beanId) {
return beans.get(beanId);
}
//委托IOC容器创建一个bean
//clazz 要创建的bean 的class , paramBeanIds 要创建的bean的class的构造方法所需要的参数Id们
public void setBean(Class<?> clazz, String beanId , String... paramBeanIds) {
// 1.组装构造方法的参数值
Object[] paramValues = new Object[paramBeanIds.length];
for (int i = 0; i < paramBeanIds.length; i++) {
paramValues[i] = beans.get(paramBeanIds[i]);
}
// 2.调用构造方法实例化bean
Object bean = null;
for (Constructor<?> constructor:
clazz.getConstructors()) {
try {
bean = constructor.newInstance(paramValues);
} catch (InstantiationException e) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {
}
}
if (bean == null){
throw new RuntimeException("找不到合适的方法实例化bean");
}
// 3.将实例化的bean 放入beans
beans.put(beanId , bean);
}
}
import car.Audi;
import car.Buick;
import humen.Humen;
import humen.ZhangSan;
import org.junit.Before;
import org.junit.Test;
public class IocTest {
private IocContainer iocContainer = new IocContainer();
@Before
public void before() {
iocContainer.setBean(Audi.class , "audi");
iocContainer.setBean(Buick.class , "buick");
iocContainer.setBean(ZhangSan.class , "zhangsan","audi");
iocContainer.setBean(ZhangSan.class , "lisi","buick");
}
@Test
public void test(){
Humen zhangSan = (Humen) iocContainer.getBean("zhangsan");
zhangSan.goHome();
Humen liSi = (Humen) iocContainer.getBean("lisi");
liSi.goHome();
}
}
Spring IOC 实例化Bean
默认构造方法实例化Bean
<bean id="bean1" name="bean1_1" class="lesson2.Bean1"></bean>
<alias name="bean1" alias="bean12"></alias>
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
Bean1 bean1 = context.getBean("bean1" , Bean1.class);
System.out.println("bean1 = " + bean1)
通过静态工厂方法实例化Bean
<bean class="lesson2.Bean2Factory" factory-method="getBean2" id="bean2"></bean>
Bean2 bean2 = context.getBean("bean2" , Bean2.class);
System.out.println("Bean2 = " +bean2);
通过实例工厂方法实例化Bean
<bean class="lesson2.Bean3Factory" id="bean3Factory"></bean>
<bean class="lesson2.Bean3" factory-bean="bean3Factory" factory-method="getBean3"
id="bean3"></bean>
Bean3 bean3 = context.getBean("bean3" , Bean3.class);
System.out.println("bean3 + " +bean3);
整个demo的例子
<?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-2.5.xsd">
<bean id="bean" class="lesson1.Bean"></bean>
<bean id="bean1" name="bean1_1" class="lesson2.Bean1"></bean>
<alias name="bean1" alias="bean12"></alias>
<bean class="lesson2.Bean2Factory" factory-method="getBean2" id="bean2"></bean>
<bean class="lesson2.Bean3Factory" id="bean3Factory"></bean>
<bean class="lesson2.Bean3" factory-bean="bean3Factory" factory-method="getBean3"
id="bean3"></bean>
</beans>
package lesson2;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Bean1Test {
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
Bean1 bean1 = context.getBean("bean1" , Bean1.class);
System.out.println("bean1 = " + bean1);
Bean2 bean2 = context.getBean("bean2" , Bean2.class);
System.out.println("Bean2 = " +bean2);
Bean3 bean3 = context.getBean("bean3" , Bean3.class);
System.out.println("bean3 + " +bean3);
Bean1 bean1_1 = context.getBean("bean1_1" , Bean1.class);
System.out.println("bean1_1 = " + bean1_1);
Bean1 bean12 = context.getBean("bean12" , Bean1.class);
System.out.println("bean12 = " + bean12 );
}
}
package lesson2;
public class Bean1 {
public Bean1 (){
System.out.println("bean1");
}
}
package lesson2;
public class Bean2 {
public Bean2() {
System.out.println("Bean.Bean2");
}
}
package lesson2;
public class Bean2Factory {
public static Bean2 getBean2(){
return new Bean2();
}
}
package lesson2;
public class Bean3 {
public Bean3() {
System.out.println("Bean2 hh");
}
}
package lesson2;
public class Bean3Factory {
public Bean3 getBean3() {
return new Bean3();
}
}
注入Bean
通过构造方法注入Bean
<bean class="lesson3.AnotherBean" id="anotherBean"></bean>
<bean class="lesson3.Bean" id="bean4">
<!-- index 标识是构造方法的第几个参数 value , ref 对参数赋值 value简单类型 , ref复杂类型-->
<!-- index name type 三个三个参数 唯一能够指示那个参数就可以-->
ref映射的是bean的id
<constructor-arg index="0"
type="lesson3.AnotherBean"
ref="anotherBean"></constructor-arg>
<constructor-arg index="1" type="java.lang.String" value="zzp"></constructor-arg>
<!--set方法注入-->
<property name="anotherBean1" ref="anotherBean"></property>
<property name="string1" value="zzp出现"></property>
</bean>
通过set方法注入Bean
<bean class="lesson3.AnotherBean" id="anotherBean"></bean>
<bean class="lesson3.Bean" id="bean4">
<!--set方法注入-->
<property name="anotherBean1" ref="anotherBean"></property>
<property name="string1" value="zzp出现"></property>
</bean>
以上俩种的简便写法
<!-- 简便写法-->
<!-- <bean class="lesson3.Bean" id="bean"-->
<!-- c:anotherBean-ref="anotherBean" c:string="简便写法"-->
<!-- p:anotherBean1-ref="anotherBean"-->
<!-- p:string1="zzp简便写法"></bean>-->
集合类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"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:p = "http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<!-- lesson3-->
<bean class="lesson3.AnotherBean" id="anotherBean"></bean>
<bean class="lesson3.Bean" id="bean">
<!-- index 标识是构造方法的第几个参数 value , ref 对参数赋值 value简单类型 , ref复杂类型-->
<!-- index name type 三个三个参数 唯一能够指示那个参数就可以-->
<constructor-arg index="0"
type="lesson3.AnotherBean"
ref="anotherBean"></constructor-arg>
<constructor-arg index="1" type="java.lang.String" value="zzp"></constructor-arg>
<property name="anotherBean1" ref="anotherBean"></property>
<property name="string1" value="zzp"></property>
<property name="stringList">
<list>
<value>aaaa</value>
<value>bbbb</value>
</list>
</property>
<property name="anotherBeanList">
<list>
<ref bean="anotherBean"></ref>
<ref bean="anotherBean"></ref>
</list>
</property>
<property name="stringSet">
<set>
<value>aaaa</value>
<value>bbbb</value>
</set>
</property>
<property name="anotherBeanSet">
<set>
<ref bean="anotherBean"></ref>
<ref bean="anotherBean"></ref>
</set>
</property>
<property name="stringStringMap">
<map>
<entry key="ccc" value="dddd"></entry>
<entry key="eee" value="ffff"></entry>
</map>
</property>
<property name="anotherBeanMap">
<map>
<entry key-ref="anotherBean" value-ref="anotherBean"></entry>
</map>
</property>
<property name="properties">
<props>
<prop key="aaaaa">bbbbb</prop>
</props>
</property>
</bean>
<!-- lesson3-->
</beans>
null值的注入
<property name="anotherBean2">
<null></null>
</property>
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"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:p = "http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean class="lesson4.Bean2" id="bean2" scope="singleton"></bean>
<bean id="bean1" class="lesson4.Bean1">
<property name="bean2" ref="bean2"></property>
</bean>
</beans>
Singleton作用域
同一个上下文的环境是产生一个单例,不同的上下文环境产生不同的单例
package lesson4;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Lesson4Test {
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("lesson4.xml");
Bean2 bean2_1 = context.getBean("bean2" , Bean2.class);
System.out.println("bean2_1 = " + bean2_1);
Bean2 bean2_2 = context.getBean("bean2" , Bean2.class);
System.out.println("bean2_2 = " + bean2_2);
Bean1 bean1 = context.getBean("bean1" , Bean1.class);
System.out.println("bean1" + bean1);
ApplicationContext context1 = new ClassPathXmlApplicationContext("lesson4.xml");
Bean2 bean2_3 = context1.getBean("bean2" , Bean2.class);
System.out.println("bean2_1 = " + bean2_1);
Bean2 bean2_4 = context1.getBean("bean2" , Bean2.class);
System.out.println("bean2_2 = " + bean2_2);
}
}
prototype 作用域
package lesson4;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Lesson4Test {
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("lesson4.xml");
Bean2 bean2_1 = context.getBean("bean2" , Bean2.class);
System.out.println("bean2_1 = " + bean2_1);
Bean2 bean2_2 = context.getBean("bean2" , Bean2.class);
System.out.println("bean2_2 = " + bean2_2);
Bean1 bean1 = context.getBean("bean1" , Bean1.class);
System.out.println("bean1" + bean1);
// ApplicationContext context1 = new ClassPathXmlApplicationContext("lesson4.xml");
// Bean2 bean2_3 = context1.getBean("bean2" , Bean2.class);
// System.out.println("bean2_1 = " + bean2_1);
// Bean2 bean2_4 = context1.getBean("bean2" , Bean2.class);
// System.out.println("bean2_2 = " + bean2_2);
}
}
Web 环境作用域
自定义作用域
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"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:p = "http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean class="lesson1.Bean" id="bean" scope="singleton"></bean>
</beans>
package lesson1;
public class Bean {
public Bean() {
System.out.println("Bean已经被创建" + true);
}
}
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import lesson1.Bean;
public class Lesson1Test {
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
System.out.println("context已经被创建");
Bean bean = context.getBean("bean" , Bean.class);
System.out.println("bean = " +bean);
}
}
Bean已经被创建true
context已经被创建
bean = lesson1.Bean@59d016c9
singleton作用域在初始化时就已经将bean加载好了
其他作用域是不会做初始化时加载bean
<bean class="lesson1.Bean" id="bean" scope="singleton" lazy-init="true"></bean>
context已经被创建
Bean已经被创建true
bean = lesson1.Bean@794cb805
加上这个标签就变为了懒加载
如果所有bean 都需要懒加载 :在beans标签加default-lazy-init=“true”
bean 初始化及销毁
如果在Bean 实例化后执行一些逻辑 ,俩种方法
- 使用init-method
- Bean 实现InitializingBean接口
如果在Bean 销毁后执行一些逻辑 ,俩种方法
- 使用destory-method
- Bean 实现DisposableBean接口
单例模式的销毁在context销毁时销毁
package lesson1;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
public class Bean implements InitializingBean , DisposableBean {
public Bean() {
System.out.println("Bean已经被创建" + true);
}
public void onInit(){
System.out.println("bean.onInit");
}
public void onDestroy(){
System.out.println("bean.onDestroy");
}
@Override
public void destroy() throws Exception {
System.out.println("bean.destroy");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("bean.afterPropertiesSet");
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:p = "http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean class="lesson1.Bean"
init-method="onInit" destroy-method="onDestroy"
id="bean" ></bean>
</beans>
package lesson1;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
public class Bean implements InitializingBean , DisposableBean {
public Bean() {
System.out.println("Bean已经被创建" + true);
}
public void onInit(){
System.out.println("bean.onInit");
}
public void onDestroy(){
System.out.println("bean.onDestroy");
}
@Override
public void destroy() throws Exception {
System.out.println("bean.destroy");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("bean.afterPropertiesSet");
}
}
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"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean class="lesson2.ParentClass" abstract="true"//不需要实例化的Bean id="parentClass">
<property name="attribute1" value="attribute1"></property>
<property name="attribute2" value="attribute2"></property>
<property name="attribute3" value="attribute3"></property>
</bean>
<bean class="lesson2.Class1" id="class1" parent="parentClass">
<property name="attribute4" value="attribute4"></property>
<property name="attribute5" value="attribute5"></property>
</bean>
<bean class="lesson2.Class2" id="class2" parent="parentClass">
<property name="attribute7" value="attribute7"></property>
<property name="attribute8" value="attribute8"></property>
</bean>
</beans>
package lesson2;
public class ParentClass {
private String attribute1;
private String attribute2;
private String attribute3;
public String getAttribute3() {
return attribute3;
}
public void setAttribute3(String attribute3) {
this.attribute3 = attribute3;
}
public String getAttribute1() {
return attribute1;
}
public void setAttribute1(String attribute1) {
this.attribute1 = attribute1;
}
public String getAttribute2() {
return attribute2;
}
public void setAttribute2(String attribute2) {
this.attribute2 = attribute2;
}
}
package lesson2;
public class Class1 extends ParentClass{
private String attribute4;
private String attribute5;
public String getAttribute4() {
return attribute4;
}
public void setAttribute4(String attribute4) {
this.attribute4 = attribute4;
}
public String getAttribute5() {
return attribute5;
}
public void setAttribute5(String attribute5) {
this.attribute5 = attribute5;
}
@Override
public String toString() {
return "Class1{" +
"attribute4='" + attribute4 + '\'' +
"attribute1='" + getAttribute1() + '\'' +
"attribute2='" + getAttribute2() + '\'' +
"attribute3='" + getAttribute3() + '\'' +
", attribute5='" + attribute5 + '\'' +
'}';
}
}
package lesson2;
public class Class2 extends ParentClass{
private String attribute7;
private String attribute8;
public String getAttribute7() {
return attribute7;
}
public void setAttribute7(String attribute7) {
this.attribute7 = attribute7;
}
public String getAttribute8() {
return attribute8;
}
public void setAttribute8(String attribute8) {
this.attribute8 = attribute8;
}
@Override
public String toString() {
return "Class2{" +
"attribute7='" + attribute7 + '\'' +
", attribute8='" + attribute8 + '\'' +
", attribute1='" + getAttribute1() + '\'' +
", attribute2='" + getAttribute2() + '\'' +
", attribute3='" + getAttribute3() + '\'' +
'}';
}
}
Spring 注解的使用
@Component(value = "bean2") //被注解的将有IOC管理 ,id 为 类名的小写 , 通用型注解
@Controller:被标注在Controller层
@Service:被标注在Service
@Repository: 被标注在Dao层
bean的别名
package lesson;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class MyBean {
private AnotherBean anotherBean1;
private AnotherBean anotherBean2;
@Autowired
private AnotherBean anotherBean3;
private List<String> stringList;
public List<String> getStringList() {
return stringList;
}
@Autowired
@Qualifier("StringList")
public void setStringList(List<String> stringList) {
this.stringList = stringList;
}
public AnotherBean getAnotherBean1() {
return anotherBean1;
}
@Autowired
public void setAnotherBean1(AnotherBean anotherBean1) {
this.anotherBean1 = anotherBean1;
}
public AnotherBean getAnotherBean2() {
return anotherBean2;
}
@Autowired
public void setAnotherBean2(AnotherBean anotherBean2) {
this.anotherBean2 = anotherBean2;
}
@Autowired
public MyBean(AnotherBean anotherBean1) {
this.anotherBean1 = anotherBean1;
}
@Override
public String toString() {
return "MyBean{" +
"anotherBean1=" + anotherBean1 +
", anotherBean2=" + anotherBean2 +
", anotherBean3=" + anotherBean3 +
'}';
}
}
package lesson;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
@Component
public class AnotherBean {
}
package lesson;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import java.util.ArrayList;
import java.util.List;
@Configuration
@ComponentScan("lesson")
public class MyConfigruation {
@Bean("StringList")
public List<String> stringList(){
List<String> list = new ArrayList<>();
list.add("zzp");
list.add("zzp1");
return list;
}
@Bean
@Order(34)
public String string1(){
return "222";
}
@Bean
@Order(23)
public String string2(){
return "333";
}
}