Spring框架1——IOC容器
一 初识IOC。
1.创建一个空项目,导入相关的jar包。在官网下载Spring压缩包,以下与Spring相关的jar包在其libs目录下找到。
<!-- commons-logging-1.2.jar 日志 spring-beans-5.3.9.jar spring-context-5.3.9.jar spring-core-5.3.9.jar spring-expression-5.3.9.jar -->
2.编写一个User类。
public class User { public void say(){ System.out.println("哈哈哈"); } }
3.编写一个xml文件,注册User类。
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="user" class="com.wsl.demo.dao.User"/> </beans>
4.编写测试类,观察结果。
public class TestDemo { @Test public void testUser(){ ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml"); User user= context.getBean("user", User.class); user.say();//哈哈 } }
二 什么是IOC(控制反转)?
Spring IOC 容器,负责实例化、配置和组装 bean。容器通过读取配置元数据来获取关于要实例化、配置和组装哪些对象的指令。配置元数据以 XML、Java 注释或 Java 代码表示。这三句话很好的概括了开头的案例:
- 通过容器获得对象并非传统的new:User user1 = context.getBean("user1", User.class);
- 容器读取配置元数据:ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
- 案例采用的是xml方式配置元数据。
Spring框架管理对象创建和生命周期的机制称之为控制反转,使用IOC目的是为了降低耦合度。
三 IOC原理。
1.工厂模式,xml解析,反射。

2.IOC思想基于IOC容器完成,IOC容器底层就是对象工厂。Spring的IOC容器实现依靠BeanFactory接口和ApplicationContext接口。

四 IOC容器——管理Bean。
操作:1.创建对象 2.注入属性(DI) 方式:1.xml 2.注解
1. xml方式
1.1 属性注入
<?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:p="http://www.springframework.org/schema/p" <!-- 使用p名称空间时引入--> xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--通过set方法注入属性--> <bean id="user1" class="com.wsl.bean.User"> <property name="name" value="张三"/> <property name="age" value="19"/> </bean> <!--通过构造方法注入属性--> <bean id="user2" class="com.wsl.bean.User"> <constructor-arg name="age" value="19"/> <constructor-arg name="name" value="李四"/> </bean> <!--通过p名称空间注入--> <bean id="user3" class="com.wsl.bean.User" p:name="王五" p:age="19"/> </beans>
属性注入——外部bean,内部bean,级联赋值
<!--外部bean--> <bean id="stu" class="com.wsl.bean.Student"> <property name="name" value="肖清芳"/> <property name="address" ref="adder"/> </bean> <bean id="adder" class="com.wsl.bean.Address"> <constructor-arg name="name" value="邙山"/> <constructor-arg name="number" value="2"/> </bean> <!--内部bean--> <bean id="stu1" class="com.wsl.bean.Student"> <property name="name" value="陆大有"/> <property name="address"> <bean class="com.wsl.bean.Address"> <property name="name" value="小莲子山"/> <property name="number" value="1"/> </bean> </property> </bean> <!--级联赋值 第一种方式就是外部bean,这里是第二种方式--> <bean id="stu2" class="com.wsl.bean.Student"> <property name="name" value="沙尔汗"/> <property name="address" ref="address1"/> <property name="address.name" value="洛阳"/> </bean> <bean id="address1" class="com.wsl.bean.Address"> <property name="number" value="1"/> </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.xsd"> <!--集合注入 方式一--> <bean id="hero1" class="com.wsl.bean.Hero"> <!--数组--> <property name="assistants"> <array> <value>李元芳</value> <value>张环</value> </array> </property> <!--List--> <property name="enemy"> <list> <value>沙尔汗</value> <value>贺鲁</value> </list> </property> <!--Set--> <property name="way"> <set> <value>便宜行事</value> <value>黜置使大人</value> </set> </property> <!--Map,这里演示key为对象的情况--> <property name="map"> <map> <entry key-ref="team1" value="蚍蜉撼树,螳臂当车,不自量力"/> <entry key-ref="team2" value="井底之蛙,夜郎自大"/> </map> </property> </bean> <bean id="team1" class="com.wsl.bean.Team"> <property name="name" value="蛇灵"/> <property name="rank" value="1000"/> </bean> <bean id="team2" class="com.wsl.bean.Team"> <property name="name" value="铁手团"/> <property name="rank" value="999"/> </bean> </beans>
<?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:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> <!-- 集合注入 方式二--> <util:list id="hobby"> <value>唱</value> <value>跳</value> <value>打篮球</value> </util:list> <!-- 集合里面是对象--> <util:list id="pets"> <ref bean="pet1"/> <ref bean="pet2"/> </util:list> <bean id="cxk" class="com.wsl.bean.People"> <property name="hobby" ref="hobby"/> <property name="pets" ref="pets"/> </bean> <bean id="pet1" class="com.wsl.bean.Pet"> <property name="name" value="小公鸡"/> <property name="info" value="咯咯咯"/> </bean> <bean id="pet2" class="com.wsl.bean.Pet"> <property name="name" value="小母鸡"/> <property name="info" value="下蛋蛋"/> </bean> </beans>
1.2 普通Bean与工厂Bean
普通Bean:配置文件中定义的bean类型就是返回类型 工厂Bean: 配置文件中定义的bean类型跟返回类型可以不同 上面看到了很多普通bean,下面就只介绍工厂bean了。
public class MyBean implements FactoryBean<Pet> {//1.定义一个类使其实现FactoryBean接口 @Override public Pet getObject() throws Exception {//2.重写getObject()方法设置其返回类型 Pet pet = new Pet(); pet.setName("dog"); pet.setInfo("汪汪汪"); return pet; } } <!--配置bean--> <bean id="myBean" class="com.wsl.bean.MyBean"/> @Test public void testBean(){ ApplicationContext context = new ClassPathXmlApplicationContext("bean5.xml"); //配置是MyBean类型,返回类型却是Pet类型 Pet pet = context.getBean("myBean", Pet.class); }
Bean的作用域

<!--将scope设置成多实例-->
<bean id="animal" class="com.wsl.bean.Animal" scope="prototype"/>
Animal animal = context.getBean("animal", Animal.class);
Animal animal1 = context.getBean("animal", Animal.class);
System.out.println(animal);
System.out.println(animal1);
//得到两个不同的对象
com.wsl.bean.Animal@738dc9b
com.wsl.bean.Animal@3c77d488
<!--默认是单实例-->
<bean id="cxk" class="com.wsl.bean.People"/>
People cxk = context.getBean("cxk", People.class);
People cxk1 = context.getBean("cxk", People.class);
System.out.println(cxk);
System.out.println(cxk1);
//得到两个相同的对象
com.wsl.bean.People@dc7df28
com.wsl.bean.People@dc7df28
1.3 Bean的七大生命周期
//1.编写测试类 public class Car { private String type; public String getType() { return type; } public Car() { System.out.println("1.调用无参构造"); } public void setType(String type) { System.out.println("2.为属性设置值"); this.type = type; } public void initMethod(){ System.out.println("4.调用初始化方法!"); } public void destroyMethod(){ System.out.println("7.调用销毁方法!"); } } //2.编写一个类实现BeanPostProcessor接口 public class ProcessModel implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("3.初始化前调用后置处理器方法"); return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName); } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("5.初始化后调用后置处理器方法"); return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName); } } //3.配置Bean <!--设置初始化和销毁方法--> <bean id="car" class="com.wsl.bean.Car" destroy-method="destroyMethod" init-method="initMethod"> <property name="type" value="公交车"/> </bean> <bean id="process" class="com.wsl.bean.ProcessModel"/> //4.编写测试代码 @Test public void testProcess(){ ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean6.xml"); Car car= context.getBean("car", Car.class); System.out.println("6.使用:"+car.getType()); context.close(); } //5.观察结果 1.调用无参构造 2.为属性设置值 3.初始化前调用后置处理器方法 4.调用初始化方法! 5.初始化后调用后置处理器方法 6.使用:公交车 7.调用销毁方法!
1.4 自动装配
<!-- 自动装配 bean标签的autowire属性开启 byName: 根据属性名称装配 若id与属性名称不一致,注入失败(为null)但不会报错 byType: 根据属性类型装配 若有多个相同类型的bean直接报错 --> <bean id="master" class="com.wsl.bean.Master" autowire="byName"/> <bean id="pet" class="com.wsl.bean.Pet"/>
1.5 外部属性文件
<?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:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!--读取外部属性文件为属性设置值--> <!--1.将我们要设置的属性值写在一个properties文件中 如:name="cxk" message="唱跳rap" --> <!--2.引入context名称空间 xmlns:context="http://www.springframework.org/schema/context" http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd --> <!--3.使用context标签就可以将properties文件引进来了--> <context:property-placeholder location="classpath:petset.properties"/> <!--使用4.${*} 如:${name}就将”cxk“设置给了pet的name属性 --> <bean id="pet" class="com.wsl.bean.Pet"> <property name="name" value="${name}"/> <property name="info" value="${message}"/> </bean>
2.注解
2.1创建对象
<!--1. 引入spring-aop-5.3.9.jar--> <!--四个注解: @Component(value = "cxk") @Repository @Controller @Service 他们作用一样,value值可以省略 --> <!--2.在类上添加注解 @Component(value = "cxk") public class User { public void say(){ 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" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!--3.开启注解扫描--> <context:component-scan base-package="com.wsl.demo"/> </beans>
<!-- 组件扫描细节--> <!-- 1.想要扫描多个包可以用逗号隔开,也可以设置成上一级目录--> <!-- 2.组件扫描配置 设置use-default-filters="false" 明白这两个单词意思: include:包括,包含 exclude:将..排除在外,除了..之外 --> <context:component-scan base-package="com.wsl.demo.dao" use-default-filters="false"> <!-- 这个表示只扫描包下带的@Controller注解--> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan> <context:component-scan base-package="com.wsl.demo.dao" use-default-filters="false"> <!-- 这个表示扫描包下除了@Controller其他注解--> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan>
2.2属性注入
<!-- 开启注解扫描--> <context:component-scan base-package="com.wsl.demo"/> <!-- 四个注解: @Autowired: 根据类型注入 @Qualifier 根据名称注入 与Autowired一起使用 @Resource 既可以根据类型又可以根据名称注入 这个注解是javax下的而并非spring的,所以官方不建议使用此注解 @Value 普通属性注入 --> <!--用法如下 将Dog对象注入 @Controller public class Cat { 下面三个任选一个即可 @Autowired 或 @Autowired @Qualifier(value = "dog1") 或 @Resource(name = "dog1") private Dog dog; }
@Service(value = "dog1") public class Dog { @Value(value = "小白") private String name; } -->
2.3 完全注解开发
<!-- 使用注解时xml只配置了包扫描,因此我们可以尝试用配置类代替xml配置文件--> <!-- 1.编写配置类 @Configuration//成为配置类,代替xml文件 @ComponentScan(basePackages = {"com.wsl.demo"})//扫描包 public class SpringConfig { } --> <!--2.编写测试类 因为我们未使用xml文件,因此有些许不同 @Test public void testMethod2(){ 读取配置类 ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); Cat cat = context.getBean("cat", Cat.class); cat.say(); } -->

浙公网安备 33010602011771号