三种XML管理、创建bean的方式:Spring Ioc是Spring公司对“控制反转”思想的实现,运用xml来管理和创建bean
基于构造方法实例对象。
基于静态工厂实例化对象。
基于工厂实例方法实例化对象。
实体类
package pers.thc.spring.IoC.entity;public class Apple { private String title; private String color; private String origin; public Apple(){} public Apple(String title, String color, String origin) { this.title = title; this.color = color; this.origin = origin; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public String getOrigin() { return origin; } public void setOrigin(String origin) { this.origin = origin; } @Override public String toString() { return "Apple{" + "title='" + title + ''' + ", color='" + color + ''' + ", origin='" + origin + ''' + '}'; }}
package pers.thc.spring.IoC.entity;public class Child { private String name; private Apple apple; public Child(){} public Child(String name, Apple apple) { this.name = name; this.apple = apple; } @Override public String toString() { return "Child{" + "name='" + name + ''' + ", apple=" + apple + '}'; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Apple getApple() { return apple; } public void setApple(Apple apple) { this.apple = apple; }}
静态工厂类
package pers.thc.spring.IoC.factory;import pers.thc.spring.IoC.entity.Apple;public class AppleFactory { public static Apple createSweetApple(){ Apple apple = new Apple("红富士", "深红", "欧洲"); return apple; }}
实例工厂类
package pers.thc.spring.IoC.factory;import pers.thc.spring.IoC.entity.Apple;public class AppleFactoryInstance { public Apple createSweetApple(){ Apple apple = new Apple("红富士", "深红", "欧洲"); return apple; }}
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="UTF-8"?>
package pers.thc.spring.IoC;import org.springframework.context.support.ClassPathXmlApplicationContext;import pers.thc.spring.IoC.entity.Apple;import pers.thc.spring.IoC.entity.Child;public class SpringApplication { public static void main(String[] args) { String configLocations[]=new String[]{ "classpath:applicationContext.xml", "classpath:applicationContext1.xml"}; //应用上下文加载顺序与字符串先后顺序有关 //启动IoC容器// ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(configLocations); //利用getBean来获取相应的实例对象// Apple sweetApple = (Apple)context.getBean("sweetApple"); Apple sweetApple = context.getBean("sweetApple", Apple.class);//由于sweetApple在两个配置文件中都有,故后加载的配置文件中的sweetApple会覆盖掉先加载配置文件中的sweetApple Child Lily = context.getBean("Lily", Child.class); Child lily = context.getBean("lily", Child.class);//通过name标签可以设置多个bean标识,此处用lily标识获取实例对象 Apple apple = context.getBean("pers.thc.spring.IoC.entity.Apple", Apple.class);//若bean没有id、name标签,则通过完整类名获取实例对象 Apple apple1 = context.getBean("apple1", Apple.class); Apple apple2 = context.getBean("apple2", Apple.class); Apple apple3 = context.getBean("apple3", Apple.class); Apple apple4 = context.getBean("apple4", Apple.class); System.out.println(sweetApple); System.out.println(Lily); System.out.println(lily); System.out.println(apple); System.out.println(apple1); System.out.println(apple2); System.out.println(apple3); System.out.println(apple4); }}
路径表达式:classpath:config.xml 扫描classpath根路径(不包含jar)的config.xml
classpath:pers/thc/config.xml 扫描classpath下(不包含jar)pers.thc包中的config.xml
classpath*:pers/thc/config.xml 扫描classpath下(包含jar)pers.thc包中的config.xml
classpath:config-*.xml 扫描classpath根路径下所有一config-开头的XML文件
classpath:persconfig.xml 扫描pers包下(包含任何子包)的config.xml file:c/:config.xml 扫描c盘根路径config.xml
两种对象依赖注入方式:setter注入对象(property)
构造方法注入对象(constructor-arg)
IoC模拟团队分工:bookshop 利用不同的配置文件,约定好bean的id,建立依赖关系(service的parent context为dao),实现分工合作。 其次,利用IoC容器还可以实现对象之间的解耦,当dao层修改实现细节时,秩序保证bean的id不变,service层不需要进行任何改变。
注入集合对象:通过“公司资产配置清单”案例学习集合类型动态注入
公司实体类
package pers.thc.spring.IoC.companyProperties.entity;import java.util.List;import java.util.Map;import java.util.Properties;public class Company { private List
电脑实体类
package pers.thc.spring.IoC.companyProperties.entity;public class Computer { private String brand; private String type; private String sn; private Float price; public Computer() { } public Computer(String brand, String type, String sn, Float price) { this.brand = brand; this.type = type; this.sn = sn; this.price = price; } @Override public String toString() { return "Computer{" + "brand='" + brand + ''' + ", type='" + type + ''' + ", sn='" + sn + ''' + ", price=" + price + '}'; } public String getBrand() { return brand; } public void setBrand(String brand) { this.brand = brand; } public String getType() { return type; } public void setType(String type) { this.type = type; } public String getSn() { return sn; } public void setSn(String sn) { this.sn = sn; } public Float getPrice() { return price; } public void setPrice(Float price) { this.price = price; }}
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
Application类
package pers.thc.spring.IoC.companyProperties;import org.springframework.context.support.ClassPathXmlApplicationContext;import pers.thc.spring.IoC.companyProperties.entity.Company;import pers.thc.spring.IoC.companyProperties.entity.Computer;public class CompanyPropertiesApplication { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext-company-properties.xml"); Company company = context.getBean("company", Company.class); System.out.println(company); //获取容器内所有beanId数组 String[] names = context.getBeanDefinitionNames(); for (String name : names) { System.out.println(name); } Computer computer = context.getBean("pers.thc.spring.IoC.companyProperties.entity.Computer#1", Computer.class); System.out.println(computer);//获取匿名bean的方法-2,通过类名全称#序号来获取相应的bean对象。序号为0,1,2……,按applicationContext.xml中的顺序递推 }}
bean scope属性:bean scope属性用于决定对象何时被创建与作用范围
bean scope配置将影响容器内对象的数量
默认情况下bean会在IoC容器创建后自动实例化,全局唯一
bean scope属性清单:singleton 单例(默认值),每一个容器有且只有唯一的实例,实例会被全局共享。单例多线程,但存在线程安全风险。 singleton线程安全问题,a=2(用户1)a.setNum(1)->a对象num=1,(用户2)sout(a.getNum())->本应输出2,现输出1
prototype 多例,每次使用时都会创建一个实例
request web环境下,每一次独立请求存在唯一实例
session web环境下,每一次session存在有唯一实例
global session portlet的web应用的共享session中
websocket 每一次websocket连接中存在唯一实例
singleton(左)和prototype(右)对比:对象数量:全局唯一 存在多个
实例化时机:IoC容器启动时 getBean()或对象注入时
线程安全问题: 存在 不存在
执行效率:高 低
bean的生命周期:容器行为:Ioc容器准备初始化解析XML->为对象注入属性->IoC容器初始化完毕->IoC容器准备销毁
对象行为:对象实例化执行构造方法->调用init-method初始化方法->执行业务逻辑->调用destroy-method释放资源
Order实体类
package pers.thc.spring.IoC.lifecycle;public class Order { private Float price; private Integer quantity; private Float total; public Order(){ System.out.println("创建Order对象,"+this); } public void init(){ System.out.println("执行init()方法"); total=price*quantity; } public void destroy(){ System.out.println("释放与订单对象相关的资源"); } public void pay(){ System.out.println("订单金额为:"+total); } public Float getPrice() { return price; } public void setPrice(Float price) { System.out.println("设置price:"+price); this.price = price; } public Integer getQuantity() { return quantity; } public void setQuantity(Integer quantity) { System.out.println("设置quantity:"+quantity); this.quantity = quantity; } public Float getTotal() { return total; } public void setTotal(Float total) { this.total = total; }}
application Context.xml
<?xml version="1.0" encoding="UTF-8"?>
Application类
package pers.thc.spring.IoC.lifecycle;import org.springframework.context.support.ClassPathXmlApplicationContext;public class LifeCycleApplication { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext-lifecycle.xml"); System.out.println("========IoC容器已初始化========"); Order order1 = context.getBean("order1", Order.class); order1.pay(); context.registerShutdownHook();//调用destroy-method方法销毁bean实例 }}
注解开发: 三类注解
组件装配注解-声明当前类的功能和职责 四类组件类型注解:
@Component 组件注解,通用注解,被注解描述的类将被IoC容器管理并实例化
@Controller 语义注解,MVC控制层
@Service 语义注解,MVC业务层
@Repository 语义注解,MVC数据持久化层 开启组件扫描:
自动装配注解-根据属性特征自动注入对象 两类自动装配注解:
按类型装配:
@Autowired 按容器内对象类型动态诸如属性,由Spring机构提供
@Inject 基于JSR-330(Denpendency Inject for java)标准,其他同@Autowired,但不支持required属性
按名称装配:
@Named 与@Inject配合使用,JSR-330标准,按属性名自动装配属性
@Resource 基于JSR-250规范,优先按名称、再按类型智能匹配
元数据注解-更细化的辅助IoC容器管理对象的注解
@Primary 按类型装配时出现多个相同类型对象,拥有此注解对象优先被注入
@PostConstruct 描述方法,相当于XML中init-method配置的注解版本
@PreDestroy 描述方法,相当于XML中destroy-method配置的注解版本
@Scope 设置对象的scope属性
@Value 为属性注入静态数据
使用Java Config配置IoC容器: Java Config核心注解@Configuration 描述类,说明当前类时Java Config配置类,完全替代XML文件
@Bean 描述方法,方法返回对象将被IoC容器管理,beanId默认为方法名
@importResource 描述类,加载静态文件,可以使用@Value注解获取
@ComponentScan 描述类,同XML的context:component-scan标签
Spring与JUnit4整合Maven工程依赖spring-test
利用@RunWith(让Spring接管JUnit4的控制权)与@ContextConfiguration(初始化过程中加载哪个初始化文件)描述测试用例类
测试用例类从容器获取对象完成测试用例的执行
import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import pers.thc.spring.IoC.springtest.service.UserService;import javax.annotation.Resource;@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations = {"classpath:applicationContext-test.xml"})public class SpringTestor { @Resource private UserService userService; @Test public void testUserService(){ userService.createUser(); }}