目录
3.3、使用ApplicationContext获取IoC容器
1、Spring IOC控制反转
1.IOC控制反转,全称Inverse of Control,是一种设计理念
2.由代理人来创建与管理对象,消费者通过代理人来获取对象
3.Ioc的目的是为了降低对象之间的耦合性
4.通过加入Ioc容器将对象统一管理,让对象关联变为弱耦合
IOC控制反转:将目标对象创建的权力从最开始的消费者,转给中间的角色在容器(IOC控制反转容器)中集中管理,消费者不再对对象直接操作,由IoC容器从中进行提取,获取其中的对象。
DI(Dependency Injection)依赖注入:java通过反射技术来实现,让运行时的程序动态执行,DI在不用语言中的实现是不一样的
2、Spring
"Spring Make Java Sample"
Spring狭义上是指Spring框架(Spring Fremework),广义上指的是Spring生态体系
Microservices分布式微服务:使用可独立发展的微服务快速交付生产级功能--SpringClould
Reactive:Spring的异步、非阻塞架构意味着可以从计算资源中获得更多收益
Cloud:任何代码,任何云,无论平台如何,都可以连接和拓展服务
Web apps:用于连接到任何数据存储的快速、安全和响应式Web应用程序的框架
Serverless:无服务器编程,摆脱服务器,极致的灵活性,按需拓展并在没有需求时拓展至零
Event Driven:事件驱动,与企业集成,对业务事件做出反应,实时处理流数据
Batch:自动化任务,批处理
为什么要用Spring?
传统开发方式(Controller--Service--Dao),对象直接应用导致对象硬性关联,程序难以拓展维护,当某一层改变代码时,需要重新进行修改、测试、上线等,流程很不方便。
利用Spring在运行时基于JAVA的反射完成对象的创建和关联------DI。
使用者提取对象A,在IOC容器中将A对象的依赖B注入到A();
反射让程序运行时,将指定的对象和其他对象进行关联。
3、Spring IoC体验
3.1.在pox.xml加入Spring的依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
</dependencies>
3.2.配置applicationContext.xml
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 每个对象都放在<bean></bean>中,由IOC容器统一管理,并且为每个Bean贴上标签id-->
<!-- 当对象改变时,只需要更改property中的内容,无需更改主函数中的源代码-->
<!--在Ioc容器启动时,自动由Spring实例化Apple对象,取名为sweetApple放入容器中-->
<bean id="sweetApple" class="com.test.spring.ioc.entity.Apple">
<property name="title" value="红富士"></property>
<property name="origin" value="欧洲"></property>
<property name="color" value="红色"></property>
</bean>
<!-- 将程序中写死的部分,写活,每写一个Bean,在IOC容器启动时,会在容器中创建对应的对象-->
<bean id="sourApple" class="com.test.spring.ioc.entity.Apple">
<property name="title" value="青苹果"></property>
<property name="origin" value="中亚"></property>
<property name="color" value="绿色"></property>
</bean>
<bean id="softApple" class="com.test.spring.ioc.entity.Apple">
<property name="title" value="金帅"></property>
<property name="origin" value="中国"></property>
<property name="color" value="黄色"></property>
</bean>
</beans>
3.3、使用ApplicationContext获取IoC容器
public class SpringApplication {
public static void main(String[] args) {
//context对象就对应了Ioc容器,赋值classpath:applicationContext.xml,向Ioc容器中加入对象
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
//通过getBean的方式获取对象,传入的参数为<bean的id,对象.class>
Apple sweetApple = context.getBean("sweetApple", Apple.class);//"sweetApple"代表bean的id
System.out.println(sweetApple.getTitle());//红富士
//所谓IOC容器,就是通过配置文件applicationContext.xml,在不通过new对象的前提下,来获取对象
}
}
4、初始化IOC容器
共有三种配置IOC容器的方法
- 基于XML applicationContext.xml配置bean
- 基于注解配置bean
- 基于java代码 javaConfig配置bean
5、基于XML配置bean
使用XML创建IOC容器,bean的属性包括id(为对象类的名字)、class(为类的路径)
<property name="" value=""></property> ---为类中的属性进行赋值
//创建IOC容器并根据配置文件的<bean></bean>创建对象
ApplicationContext context = new ClassPathApplicationContext("classpath:applicationContext.xml");
<!-- bean默认用无参构造方法来创建对象-->
<bean class="com.test.Spring.IoC.entity.Apple" id="apple1"/>
6、实例化bean的三种方法
- 基于构造方法对象实例化
- 基于静态工厂实例化
- 基于工厂实例方法实例化
6.1利用构造方法参数实例化
可以通过<constructor-arg name=" " value=" ">实例化
设置为三个参数的构造方法,IOc容器被创建时,会去Apple类中寻找符合title、origin、color三个参数的构造方法
<!--通过带参构造方法实例化对象,利用反射技术赋值-->
<bean class="com.test.Spring.IoC.entity.Apple" id="apple2">
<constructor-arg name="title" value="红富士"/>
<constructor-arg name="color" value="红色"/>
<constructor-arg name="origin" value="欧洲"/>
</bean>
还可以通过类中构造方法的参数的位置对应进行赋值
<!--通过带参构造方法实例化对象,利用反射技术赋值-->
<bean class="com.test.Spring.IoC.entity.Apple" id="apple2">
<constructor-arg index="0" value="红富士"/>
<constructor-arg index="1" value="红色"/>
<constructor-arg index="2" value="欧洲"/>
</bean>
6.2利用静态工厂实例化对象
创建Factory类AppleStaticFactory,在类中创建对象并赋值,返回类对象
然后再applicationContext.xml中声明factory-method = “类的名字”
package com.test.Spring.IoC.Factory;
import com.test.Spring.IoC.entity.Apple;
public class AppleStaticFactory {
//此处方法为静态的属于AppleStaticFactory类
public static Apple createSweetApple(){
Apple apple = new Apple();
apple.setTitle("红富士");
apple.setOrigin("欧洲");
apple.setColor("红色");
return apple;
}
}
<!--静态工厂的目的,在ioc容器之外创建对象,隐藏创建对象时的具体逻辑,可以在工厂代码中加入其他逻辑-->
<bean id="apple3" class="com.test.Spring.IoC.Factory.AppleStaticFactory" factory-method="createSweetApple"/>
6.3基于工厂实例方法实例化
创建工厂类AppleFactoryInstance
package com.test.Spring.IoC.Factory;
import com.test.Spring.IoC.entity.Apple;
/**
* 工厂实例方法创建对象是指Ioc容器对工厂类进行实例化并调用对应的实例方法对象的过程
*/
public class AppleFactoryInstance {
//此处方法为非静态方法,不属于类,属于类的对象
public Apple createSweetApple(){
Apple apple = new Apple();
apple.setTitle("红富士");
apple.setOrigin("欧洲");
apple.setColor("红色");
return apple;
}
}
<!--利用工厂实例化方法创建对象,对象方法不用static时,需要先实例化工厂类-->
<!--实例化工厂类获取factory-bean,再实例化工厂类的方法-->
<bean id="factoryInstance" class="com.test.Spring.IoC.Factory.AppleFactoryInstance"/>
<bean id="apple5" factory-bean="factoryInstance" factory-method="createSweetApple"/>
实例化bean共有三种方法,主要使用第一种利用构造方法实例化bean
7.从IOC容器获取bean
要获取bean的类对象,可以使用context.getBean()方法,参数传入bean ID
Apple sweetApple = context.getBean("sweetApple",Apple.class);
Apple sweetApple = (Apple)context.getBean("sweetApple");
System.out.println(sweetApple.getTitle);
优先使用id对bean经行标识
8、classpath:路径表达式
即classpath:applicationContext.xml--加载当前路径下的--xml文件
指的是编译过后的target目录下的xml文件
加载target-classes-com-applicationContext.xml
9、属性的依赖注入
对象依赖注入有两种方法:
- 基于setter方法注入对象
- 基于构造方法注入对象
9.1基于setter方法注入对象
setter方法的注入分为静态数值的注入和对象的注入
apple通过IOC容器依赖注入到child
<!--使用setter方法为对象赋值,静态数值-->
<bean id="sweetApple" class="com.test.spring.IoC.entity.Apple">
<property name="title" value="红富士"/>
<property name="color" value="红色"/>
<property name="origin" value="欧洲"/>
<!--Spring IoC会将"19.8"自动转化成需要的类型-->
<property name="price" value="19.8"/>
</bean>
ref : 对象注入,将sweetApple与name:莉莉 关联起来
<!--创建IoC容器ApplicationContext时,
先通过setter静态创建sweetApple对象,随后通过setter将sweetApple注入到child中-->
<bean class="com.test.spring.IoC.entity.Child" id="lili">
<property name="name" value="lili"/>
<!--利用ref实现对象的注入,ref为注入对象对象的ID-->
<property name="apple" ref="sweetApple"/>
</bean>
通过上面bean的对象注入,当创建IoC容器时,会先创建Apple对象,在创建Child对象,在DI Apple对象到Child对象的apple属性中
依赖注入的优势
applicationContext-dao.xml
<!--这里的的class不能为接口对象,必须为接口的实现类BookDaoImpl-->
<bean id="bookDao" class="com.test.spring.ioc.bookshop.dao.BookDaoImpl(1/2)"/>
applicationContext-sercice.xml
<!--BookService在运行时需要用到BookDao,
BookService不需要管用到的BookDao的实现类是哪个,
只需要ref创建的Dao就可以了
-->
<bean class="com.test.spring.ioc.bookshop.service.BookService" id="bookService">
//传入ref为:"bookDao" 当接口的逻辑改变时,只需要修改bookDao的class实体类就行
<property name="bookDao" ref="bookDao"/>
</bean>
//Dao
public interface BookDao {
public void insert();
}
public class BookDaoImpl implements BookDao{
public void insert(){
System.out.println("向mysql插入一条数据");
}
}
//当接口逻辑改变时即 BookDaoImpl-->BookDaoImpl2 ,需要修改applicationContext-dao.xml
public class BookDaoImpl2 implements BookDao{
public void insert() {
System.out.println("向redis数据库表插入一条数据");
}
}
//BookService
package com.test.spring.ioc.bookshop.service;
import com.test.spring.ioc.bookshop.dao.BookDao;
public class BookService {
//此处只需要传入接口就行,方便后期需要修改时的代码的维护
private BookDao bookDao;
public void purchase(){
System.out.println("执行采购图书的业务");
bookDao.insert();
}
//getter and setter
}
public class BookShopApplication {
public static void main(String[] args) {
//按照xml.的先后顺序实例化Ioc容器
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext-*.xml");
BookService bookService = context.getBean("bookService", BookService.class);
bookService.purchase();
}
}
9.2利用构造方法实现对象的依赖注入
依赖注入是指运行时将容器内对象利用反射赋给其他对象的操作
先初始化Apple对象sourApple,再将Child对象中的属性name、apple通过基于构造方法注入
<bean id="sourApple" class="com.test.spring.IoC.entity.Apple">
<property name="title" value="青苹果"/>
<property name="color" value="绿色"/>
<property name="origin" value="中亚"/>
<!--Spring IoC会将"19.8"自动转化成需要的类型-->
<property name="price" value="9.8"/>
</bean>
<bean id="andy" class="com.test.spring.IoC.entity.Child">
<constructor-arg name="name" value="andy"/>
<!--当构造方法中存在对象时,可以使用ref传入对象,
通过IoC容器利用反射将sourApple注入到child对象中-->
<constructor-arg name="apple" ref="sourApple"/>
</bean>
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
Child child = context.getBean("andy", Child.class);
child.eat();
}
10、注入集合对象
在bean中注入的集合对象分为四类
- List
- Set
- Map
- Properties
10.1注入List
Properties 传入的key Value 只能使用字符串
package com.test.spring.ioc.entity;
import java.util.List;
import java.util.Map;
import java.util.Properties;
public class company {
private List<String> rooms;
private Map<String,computer> computers;
private Properties info;
}
package com.test.spring.ioc.entity;
public class computer {
private String brand;
private String type;
private String sn;
private Float price;
}
<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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean class="com.test.spring.ioc.entity.computer" id="c1">
<constructor-arg name="brand" value="lianxiang"/>
<constructor-arg name="type" value="taishiji"/>
<constructor-arg name="sn" value="8389283012"/>
<constructor-arg name="price" value="3085"/>
</bean>
<bean id="company" class="com.test.spring.ioc.entity.company">
<property name="rooms">
<list>
<value>2001-总裁办</value>
<value>2003-总经理办公室</value>
<value>2010-研发部办公室</value>
</list>
<!-- <set>-->
<!-- <value>2001-总裁办</value>-->
<!-- <value>2003-总经理办公室</value>-->
<!-- <value>2010-研发部办公室</value>-->
<!-- <value>2010-研发部办公室</value>-->
<!-- </set>-->
</property>
<property name="computers">
<map>
<entry key="dev-88172" value-ref="c1"/>
<entry key="dev0-88173">
<bean class="com.test.spring.ioc.entity.computer">
<constructor-arg name="brand" value="lianxiang"/>
<constructor-arg name="type" value="taishiji"/>
<constructor-arg name="sn" value="3333"/>
<constructor-arg name="price" value="3333"/>
</bean>
</entry>
</map>
</property>
<property name="info">
<props>
<prop key="phone">12345678</prop>
<prop key="address">广州市番禺区</prop>
<prop key="webSite">www.gdut.edu.cn</prop>
</props>
</property>
</bean>
</beans>
11、查看容器内的对象
要查看IOC容器内的bean对象,需要使用context.getBeanDefinitionNames()方法,返回的是String[]类型的数组
//获取容器内所有的beanNames数组
String[] beanNames = context.getBeanDefinitionNames();
for(String beanName : beanNames){
System.out.println(beanName);
System.out.println("类型:" + context.getBean(beanName).getClass().getName());
System.out.println("内容:" + context.getBean(beanName));
}
// 如果一个bean没有Id属性,则会显示class的完整路径匿名bean
//如果内部写的bean则不会被获取。
c1:
类型:com.test.spring.ioc.entity.computer
内容:computer{brand='lianxiang', type='taishiji', sn='8389283012', price=3085.0}
company:
类型:com.test.spring.ioc.entity.company
内容:company{rooms=[2001-总裁办, 2003-总经理办公室, 2010-研发部办公室], computers={dev-88172=computer{brand='lianxiang', type='taishiji', sn='8389283012', price=3085.0}, dev0-88173=computer{brand='lianxiang', type='taishiji', sn='3333', price=3333.0}}, info={webSite=www.gdut.edu.cn, phone=12345678, address=广州市番禺区}}
12、bean的scope属性
bean scope属性用于决定对象何时被创建与作用范围
bean scope配置将影响容器内对象的数量
bean scope默认值singleton(单例),指全局共享同一个对象实例,默认情况下bean会在IoC容器创建后自动实例化,全局唯一
实例化bean的时间点:singleton为创建IoC容器时创建,prototype为getBean时创建
<bean id="userDao" class="com.test.spring.ioc.Dao.UserDao" scope="prototype"/>
<bean class="com.test.spring.ioc.service.UserService" id="userService">
<property name="userDao" ref="userDao"/>
</bean>
//scope默认为单例模式
public class SpringApplication {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
}
}
//由于getBean(),则多例模式的bean不会被初始化,优先按顺序初始化scope为singleton的bean
//先初始化UserService的默认构造方法,再调用set方法时先去实例化一个UserDao对象,再set
//UserService已经创建com.test.spring.ioc.service.UserService@13c78c0b
//UserDao已创建com.test.spring.ioc.Dao.UserDao@548a9f61
//调用UserDaocom.test.spring.ioc.Dao.UserDao@548a9f61
13、bean的生命周期
<bean id="order1" class="com.test.spring.ioc.entity.order"
init-method="init" destroy-method="destory">//这里放init-method和destroy-method
<property name="price" value="19.8"/>
<property name="numbers" value="1000"/>
</bean>
package com.test.spring.ioc.entity;
public class order {
private float price;
private Integer numbers;
private float totalPrice;
public order(){
System.out.println("创建order方法");
}
public void init(){
System.out.println("执行init方法");//初始化方法1
totalPrice = price * numbers;
}
public void destory(){
System.out.println("释放与订单对象相关的资源");//销毁容器方法3
}
public void pay(){
System.out.println("订单金额为:"+totalPrice);//业务方法2
}
}
public class SpringApplication {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");//创建容器
order o1 = context.getBean("order1", order.class);//赋值于容器,init();
o1.pay();//业务逻辑方法 pay();
//销毁容器的方法 destory();
((ClassPathXmlApplicationContext)context).registerShutdownHook();
}
}
声明周期历程:
创建order方法 //执行了构造方法
设置price //bean中为对象注入属性
执行init方法 //IoC容器初始化完成
订单金额为:19800.0 //执行业务逻辑方法
释放与订单对象相关的资源 //销毁IoC容器
14、实现极简IOC容器
IOC容器的实质就是解析XML文件后,将id 、Class存入map中保存,遇到propertity时,利用反射技术将方法名进行获取,最后通过Method.invoke(对象,值)进行setter;
<dependencies>
<!-- Dom4j是java的XML解析组件-->
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>2.1.1</version>
</dependency>
<!--jaxen是XPATH的解释器-->
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.1.6</version>
</dependency>
</dependencies>
package com.test.spring.ioc.entity;
public class Apple {
private String title;
private String color;
private String origin;
}
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
<bean id="sweetApple" class="com.test.spring.ioc.entity.Apple">
<property name="title" value="红富士"/>
<property name="color" value="红色"/>
<property name="origin" value="欧洲"/>
</bean>
</beans>
package com.test.spring.ioc.context;
public interface ApplicationContext {
public Object getBean(String beanId);
}
package com.test.spring.ioc.context;
public class ClassPathApplicationContext implements ApplicationContext{
private Map iocContainer = new HashMap();
public ClassPathApplicationContext(){
try{
//获取到xml的路径
String filePath = this.getClass().getResource("/applicationContext.xml").getPath();
filePath = new URLDecoder().decode(filePath,"UTF-8");
SAXReader reader = new SAXReader();
Document document = reader.read(new File(filePath));
List<Node> beans = document.getRootElement().selectNodes("bean");
for(Node node : beans){
Element ele = (Element)node;
String id = ele.attributeValue("id");
String className = ele.attributeValue("class");
Class c = Class.forName(className);
Object obj = c.newInstance();
List<Node> properties = ele.selectNodes("property");
for(Node p : properties){
Element property = (Element)p;
String popName = property.attributeValue("name");
String popValue = property.attributeValue("value");
String setMethodName = "set"+popName.substring(0,1).toUpperCase()+popName.substring(1);
Method setMethod = c.getMethod(setMethodName,String.class);
setMethod.invoke(obj,popValue);//通过setter方法注入容器
}
iocContainer.put(id,obj);
}
System.out.println("IOc容器初始化完毕");
}catch (Exception e){
e.printStackTrace();
}
}
public Object getBean(String beanId) {
return iocContainer.get(beanId);
}
}
package com.test.spring.ioc;
import com.test.spring.ioc.context.ApplicationContext;
import com.test.spring.ioc.context.ClassPathApplicationContext;
import com.test.spring.ioc.entity.Apple;
public class Application {
public static void main(String[] args) {
ApplicationContext context = new ClassPathApplicationContext();
Apple apple = (Apple) context.getBean("sweetApple");
System.out.println(apple);
}
}
15、基于注解配置IOC容器
前面使用了XML来配置IOc容器
@Component ---通用注解
@Controller ---控制器类注解Controller
@Service ---服务类注解Service
@Repository ---业务持久层注解Dao
需要现在applicationContext.xml中配置xml
16、 基于注解创建IOC容器
Ioc容器创建时,会先去扫描xml中的base-package="com.test"目录下类是否含有注解,并将其实例化含有四个注解的类,注解创建出来的对象是单例的,其beanId为小写类型或者自己设置的("类名");
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
</dependencies>
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!-- 在IOC容器初始化时自动扫描四种组件类型注解并完成实例化
@Repository
@Service
@Controller
@Component
-->
<context:component-scan base-package="com.test"/>
</beans>
package com.test.spring.ioc.dao;
import org.springframework.stereotype.Repository;
//组件类型注解默认为beanId为类名首字母小写 beanId = userDao
//该类为数据持久化,IOc会扫描该类
@Repository
public class UserDao {
}
package com.test.spring.ioc.service;
import org.springframework.stereotype.Service;
@Service
public class UserService {
public static void main(String[] args) {
}
}
package com.test.spring.ioc.controller;
@org.springframework.stereotype.Controller
public class Controller {
public static void main(String[] args) {
}
}
package com.test.spring.ioc.utils;
import org.springframework.stereotype.Component;
@Component
public class StringUtils {
public static void main(String[] args) {
}
}
package com.test.spring.ioc;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringApplication {
public static void main(String[] args) {
//注解模式是单例的
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");//实例化对象
String[] ids = context.getBeanDefinitionNames();//获取beanId的名字
for(String s : ids){
System.out.println(s+":"+context.getBean(s));
}
}
}
//beanIdm默认为小写字母开头的类名
//controller:com.test.spring.ioc.controller.Controller@1d7acb34
//userDao:com.test.spring.ioc.dao.UserDao@48a242ce
//userService:com.test.spring.ioc.service.UserService@1e4a7dd4
//stringUtils:com.test.spring.ioc.utils.StringUtils@4f51b3e0
17、两类自动装配注解
18、元数据注解
@Scope()
@Scope("prototype")//设置单例/多例
@PostConstruct
@PostConstruct //XML中bean init-method完全相同
public void init(){
System.out.println("初始化UserService对象");
}
@Value()
@Value("${metaData}")//为属性赋予静态数值,读取config.properties的key为metaData属性值
private String metaData;
<context:property-placeholder location="classpath:comfig.properties"/>
<!--通知Spring IOC容器 初始化时 加载属性文件-->
<!--读取comfig.properties的配置文件-->
//应用程序的配置信息properties,创建配置文件
metaData = staticValue
19、基于java Config
除了使用xml或注解配置IOC容器外,还可以使用java Config配置
Spring3.0后才出现
Java Config的优势
1.完全摆脱XML的束缚,使用独立Java类管理对象与依赖
2.注解配置相对分散,利用java Config可以对配置集中管理
3.可以在编译时进行依赖检查,不容易出错
public class UserDao {}
public class UserService {
private UserDao userDao;
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
public class UserController {
private UserService userService;
public UserService getUserService() {
return userService;
}
public void setUserService(UserService userService) {
this.userService = userService;
}
}
package com.test.spring.ioc;
/**
* java Config使用java类替代XML和注解
*/
@Configuration//当前类是一个配置类,用于替代applicationContext
public class Config {
@Bean//java config利用方法创建对象,将方法返回对象放入容器,beanId = 方法名
public UserDao userDao(){
UserDao userDao = new UserDao();//new用来创建bean
return userDao;
}
@Bean
public UserService userService(){
UserService userService = new UserService();
return userService;
}
@Bean //相当于<bean id = "xxx" class = "xxx"
public UserController userController(){
UserController userController = new UserController();
return userController;
}
}
public class SpringApplication {
public static void main(String[] args) {
//基于java config配置IOC容器的初始化
ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
String[] beanId = context.getBeanDefinitionNames();
for(String id : beanId){
System.out.println(id+" "+context.getBean(id));
}
}
}
//config com.test.spring.ioc.Config$$EnhancerBySpringCGLIB$$a638b9c3@1b68b9a4
//userDao com.test.spring.ioc.Dao.UserDao@4f9a3314
//userService com.test.spring.ioc.Service.UserService@3b2c72c2
//userController com.test.spring.ioc.Controller.UserController@491666ad
20、java Config
package com.test.spring.ioc;
/**
* java Config使用java类替代XML和注解
*/
@Configuration//当前类是一个配置类,用于替代applicationContext
@ComponentScan(basePackages = "com.test")//不但加载当前的java config,还会去加载其他类是否有注解
public class Config {
@Bean//java config利用方法创建对象,将方法返回对象放入容器,beanId = 方法名
public UserDao userDao(){
UserDao userDao = new UserDao();//new用来创建bean
return userDao;
}
@Bean
@Scope("singleton")
@Primary
//参数名与上述beanId相同,可以完成在userService注入UserDao的操作
public UserService userService(UserDao userDao, EmpDao empDao){
UserService userService = new UserService();
userService.setUserDao(userDao);
userService.setEmpDao(empDao);//该s'g'h'y
return userService;
}
@Bean //<bean id = "xxx" class = "xxx"
public UserController userController(UserService userService){
UserController userController = new UserController();
userController.setUserService(userService);
return userController;
}
}
@Repository//使用注解进行实例化
public class EmpDao {
}
public class UserService {//使用java Config进行实例化
private UserDao userDao;
private EmpDao empDao;
}
21、Spring Test测试模块
Spring与JUnit整合过程
1.Maven工程依赖spring-test
2.利用@RunWith与@ContextConfiguration描述测试用例类
3.测试用例类从容器获取对象完成测试用例的执行
1.在pom.xml引入JUnit4依赖、Spring-test
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.16</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.3.8</version>
</dependency>
<!--引用JUnit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<!-- <scope>test</scope>-->
</dependency>
</dependencies>
import javax.annotation.Resource;
//将JUNIT4的执行权交给Spring Test,接管JUnit4的控制权在测试用例执行前自动初始化IOC容器
//将applicationContext中的<bean>对象实例化
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})//用于说明加载哪个配置文件!
public class SpringTestor {
//在这个类运行前IOC容器已经创建好了
//用@Resource注入属性
@Resource
private UserService userService;
@Test
public void UserService(){
userService.createUser();
}
}
<!--利用JUnit4测试前,实例化IOC容器的对象-->
<bean id="userDao" class="com.test.spring.ioc.DAO.UserDao">
</bean>
<bean class="com.test.spring.ioc.Service.UserService" id="userService">
<property name="userDao" ref="userDao"/>
</bean>