Spring IOC
Spring简介
- Spring理念
- 使现有的技术更加容易使用,本身是一个大杂烩,整合了现有的技术框架
- Spring优点
- Spring是一个轻量级的 控制反转(IOC) 和 面向切面(AOP) 的容器(框架)
控制反转(IOC)
- IOC的理解
- 本来主动权在业务层 程序调用什么由业务层决定
- 现在主动权在用户 程序调用什么由用户决定
- IOC的本质
- IOC本质就是 获得依赖对象的方式反转了
- IOC是一种编程思想,由主动的编程变成被动的接收
- DI(依赖注入)是实现IOC的一种方法
- 举个栗子春暖花开
1.Hello实体类
package com.kuang.pojo;
public class Hello {
private String name;
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Hello{" +
"name='" + name + '\'' +
'}';
}
}
2.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">
<!--使用Spring来创建对象 一个对象就是一个bean-->
<!--id:变量名;class:new 的对象;property:设置的属性-->
<bean id="hello" class="com.kuang.pojo.Hello">
<property name="name" value="Spring"></property>
</bean>
</beans>
3.测试类
import com.kuang.pojo.Hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
//获取Spring的上下文对象!
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//对象都在Spring中管理 getBean的参数就是spring配置文件中bean的id
Hello hello=(Hello)context.getBean("hello");
System.out.println(hello.toString());//Hello{name='Spring'}
}
}
4.思考问题
控制:(谁来控制对象的创建)传统应用程序的对象是由程序本身控制创建的;使用Spring后,对象是由Spring来创建的
反转:程序本身不创建对象,而变成被动的接收对象
依赖注入:就是利用set方法来进行注入的
-
IOC创建对象的方式
- 使用无参构造创建对象
- 默认
- 使用有参构造创建对象
<!--方式一:根据index下标设置--> <bean id="user" class="com.kuang.pojo.User"> <!--下标为0表示有参构造第一个参数--> <constructor-arg index="0" value="kison"/> </bean> <!--方式二:根据参数名字设置--> <bean id="user" class="com.kuang.pojo.User"> <!-- name是参数名 --> <constructor-arg name="name" value="kison"/> </bean>
- 使用无参构造创建对象
依赖注入(DI)
- 什么是依赖注入
- 依赖注入就是利用set方法来进行注入的
- 依赖:bean对象的创建依赖于容器!
- 注入:bean对象中的所有属性,由容器来注入!
- 举个栗子春暖花开(在XML中显式装配Bean)
1.实体类Student
package com.kuang.pojo;
import java.util.*;
public class Student {
private String name;
private Address address;
private String[] books;
private List<String> hobbys;
private Map<String,String> card;
private Set<String> games;
private String wife;
private Properties info;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public String[] getBooks() {
return books;
}
public void setBooks(String[] books) {
this.books = books;
}
public List<String> getHobbys() {
return hobbys;
}
public void setHobbys(List<String> hobbys) {
this.hobbys = hobbys;
}
public Map<String, String> getCard() {
return card;
}
public void setCard(Map<String, String> card) {
this.card = card;
}
public Set<String> getGames() {
return games;
}
public void setGames(Set<String> games) {
this.games = games;
}
public String getWife() {
return wife;
}
public void setWife(String wife) {
this.wife = wife;
}
public Properties getInfo() {
return info;
}
public void setInfo(Properties info) {
this.info = info;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", address=" + address.toString() +
", books=" + Arrays.toString(books) +
", hobbys=" + hobbys +
", card=" + card +
", games=" + games +
", wife='" + wife + '\'' +
", info=" + info +
'}';
}
}
2.实体类Address
package com.kuang.pojo;
public class Address {
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Address{" +
"address='" + address + '\'' +
'}';
}
}
3.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="addr" class="com.kuang.pojo.Address">
<property name="address" value="陕西"></property>
</bean>
<bean id="stu" class="com.kuang.pojo.Student">
<!-- 常量注入 -->
<property name="name" value="yk"></property>
<!-- 对象注入 -->
<property name="address" ref="addr"></property>
<!--1 数组-->
<property name="books">
<array>
<value>局中人</value>
<value>三十而已</value>
<value>猎毒</value>
</array>
</property>
<!--2 List注入-->
<property name="hobbys">
<list>
<value>听歌</value>
<value>敲代码</value>
<value>看电影</value>
</list>
</property>
<!--3 Map注入-->
<property name="card">
<map>
<entry key="中国农业银行" value="4564564564676"></entry>
<entry key="中国建设银行" value="1456682255511"></entry>
</map>
</property>
<!--4 Set注入-->
<property name="games">
<set>
<value>BOB</value>
<value>COC</value>
</set>
</property>
<!--5 Null注入-->
<!--<property name="wife" value=""></property>-->
<property name="wife"><null></null></property>
<!--6 Properties注入-->
<property name="info">
<props>
<prop key="学号">20185476</prop>
<prop key="姓名">ykk</prop>
</props>
</property>
</bean>
</beans>
4.测试类
import com.kuang.pojo.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");
Student student=(Student) context.getBean("stu");
System.out.println(student.toString());
}
}
//Student{name='yk', address=Address{address='陕西'}, books=[局中人, 三十而已, 猎毒], hobbys=[听歌, 敲代码, 看电影], card={中国农业银行=4564564564676, 中国建设银行=1456682255511}, games=[BOB, COC], wife='null', info={姓名=ykk, 学号=20185476}}
Bean作用域(scope)
- 单例模式(Singleton)
- 设置方式
<bean id="ServiceImpl" class="cn.csdn.service.ServiceImpl" scope="singleton">
- 存在一个共享的bean实例
- 每次对该bean请求时(调用容器的getBean()方法),只会返回当前共享的bean实例
- 默认模式
- 设置方式
- 原型模式(Prototype)
- 设置方式
<bean id="account" class="com.foo.DefaultAccount" scope="prototype"/>
- 存在多个bean实例
- 每次对该bean请求时(调用容器的getBean()方法),都会创建一个新的bean实例并返回
- 设置方式
- Request(一次HTTP请求),Session(一次HTTP会话),Application(全局)
Bean自动装配
- Spring中Bean的三种装配机制
- 在XML中显式装配
- 在Java中显式装配
- 隐式的自动装配(重点!!!)
- 举个栗子春暖花开(隐式的自动装配Bean)
一、隐式的自动装配之byName和byType
1.实体类Dog
package com.kuang.pojo;
public class Dog {
public void shout(){
System.out.println("wang~~");
}
}
2.实体类Cat
package com.kuang.pojo;
public class Cat {
public void shout(){
System.out.println("miao~~");
}
}
3.实体类People
package com.kuang.pojo;
public class People {
private Cat cat;
private Dog dog;
private String name;
public Cat getCat() {
return cat;
}
public void setCat(Cat cat) {
this.cat = cat;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "People{" +
"cat=" + cat +
", dog=" + dog +
", name='" + name + '\'' +
'}';
}
}
4.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="dog" class="com.kuang.pojo.Dog"></bean>
<bean id="cat" class="com.kuang.pojo.Cat"></bean>
<!--
byName原理
1 在当前类中查找所有set方法名,例如setCat方法,去掉set,同时C小写,得到字符串cat
2 在Spring容器中找id为此字符串的对象,如果有,则取出注入;如果没有,则报空指针异常
3.使用方法 autowire="byName"
byType原理
1 不管id值为什么,它都是按照类型在容器中寻找。要求同一类型的对象在容器中唯一
2 自动在容器上下文中寻找和自己对象的属性类型相同的bean
3 使用方法 autowire="byType" 其余与byName相同
-->
<bean id="people" class="com.kuang.pojo.People" autowire="byName">
<property name="name" value="ykk"></property>
</bean>
</beans>
5.测试类
import com.kuang.pojo.People;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");
People people=context.getBean("people",People.class);
people.getDog().shout();
people.getCat().shout();
}
}
二、隐式的自动装配之注解开发(重点重点!!!)
1.Spring配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--开启属性注解支持!-->
<context:annotation-config/>
<bean id="dog" class="com.kuang.pojo.Dog"></bean>
<bean id="cat" class="com.kuang.pojo.Cat"></bean>
<bean id="people" class="com.kuang.pojo.People"></bean>
</beans>
2.实体类People
package com.kuang.pojo;
import org.springframework.beans.factory.annotation.Autowired;
public class People {
@Autowired
private Cat cat;
@Autowired
private Dog dog;
private String name;
public Cat getCat() {
return cat;
}
public Dog getDog() {
return dog;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "People{" +
"cat=" + cat +
", dog=" + dog +
", name='" + name + '\'' +
'}';
}
}
3.使用@Autowired的注意事项
①@Autowired是按照类型自动装配的,即byType
②@Autowired加上@Qualifier(value=" ")是根据名称自动装配的,即byName
③@Resource很强大,如果有指定的name属性,则根据该属性按照byName方式装配;其次,进行默认的byName方式装配;最后,按照byType方式装配
④使用@Autowired注解的话,可以删除类中的set方法
⑤@Autowired(required=false) 如果为false,则对象可以为null;如果为true,对象必须存对象
使用注解开发
1.com.kuang.pojo.User
package com.kuang.pojo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component//等价于<bean id="user" class="com.kuang.pojo.User"></bean>
@Scope("singleton")
public class User {
@Value("ykk")//等价于<property name="name" value="ykk"/>
public String name;
}
2.com.kuang.dao.UserDao
package com.kuang.dao;
import org.springframework.stereotype.Repository;
@Repository
public class UserDao {
}
3.com.kuang.controller.UserController
package com.kuang.controller;
import org.springframework.stereotype.Controller;
@Controller
public class UserController {
}
4.com.kuang.service.UserService
package com.kuang.service;
import org.springframework.stereotype.Service;
@Service
public class UserService {
}
5.applocationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--指定要扫描的包 包下的注解就会生效-->
<context:component-scan base-package="com.kuang"></context:component-scan>
<!--开启属性注解支持!-->
<context:annotation-config/>
</beans>
6.测试类MyTest.java
import com.kuang.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
User user=context.getBean("user",User.class);
System.out.println(user.name);
}
}
在Java中显式装配Bean(两种方式)
1.java配置类
package com.kuang.config;
import com.kuang.pojo.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
//配置类,等价于applicationContext.xml配置文件
@Configuration //方式一 方式二
//方式一
//@ComponentScan("com.kuang.pojo")
public class UserConfig {
// 注册一个bean bean的id就相当于这个方法的名字;bean的class属性就相当于这个方法的返回值
@Bean //方式二
public User getUser(){
return new User();//返回要注入到bean的对象
}
}
2.实体类User
package com.kuang.pojo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
//方式一
//@Component
public class User {
@Value("ykk")
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
}
3.测试类
import com.kuang.config.UserConfig;
import com.kuang.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MyTest {
public static void main(String[] args) {
ApplicationContext context=new AnnotationConfigApplicationContext(UserConfig.class);
//方式一
//User user=context.getBean("user",User.class);
User user=context.getBean("getUser",User.class); //方式二
System.out.println(user.getName());
}
}