Spring IOC的简单了解、使用。
目录
Spring IOC
一、Spring IOC是什么?
二、实现SpringIOC的三种方式
三、使用步骤
1.使用XML实现SpringIOC
1.1 配置applicationContext.xml文件
1.2 配置程序入口Application类
1.3 使用XML实现IOC创建对象的三种方式
1.4 向IOC注入集合对象
2.使用注解方式实现IOC
2.1 四种组件类型注解编辑
2.2 自动装配注解编辑
2.3 元数据注解
3.使用JavaConfig的方式实现IOC
4.Spirng和JUnit4整合
IOC 是 Inversion of Control 的简写,译为“控制反转”,它不是一门技术,而是一种设计思想,是一个重要的面向对象编程法则,能够指导我们如何设计出松耦合、更优良的程序。
传统的Java应用中,一个类想要调用另一个类中的属性或方法,通常会先在其代码中通过 new Object() 的方式将后者的对象创建出来,然后才能实现属性或方法的调用。为了方便理解和描述,我们可以将前者称为“调用者”,将后者称为“被调用者”。也就是说,调用者掌握着被调用者对象创建的控制权。
但是在Spring应用中,Java对象的创建控制权掌握在IOC容器中,当某个java 实例需要另一个java实例时,创建被调用者的工作不是由调用者实现,而是由spring容器来完成,然后注入调用者,因此称为依赖注入(Dependency Injection 简称 DI)。DI在Java中是通过反射技术实现的。
有三种实现SpringIOC的方式,为:
在maven中引入spingframework的依赖:
org.springframework
spring-context
5.2.6.RELEASE
如果网络不流畅,也可以同样在maven中配置aliyun的镜像仓库:
aliyun
aliyun
https://maven.aliyun.com/repository/public
在resources目录下创建applicationCont.xml配置文件。
在Spring官网找到Springframework的Core Technologies下拉找到配置文件的表头:
在里面可以通过ClassPathXmlApplicationContext类来加载IOC中的bean
public class SpringApplication {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
UserService userService = context.getBean("userService", UserService.class);
System.out.println(userService.getUdao());
}
}
(1)通过无参的构造方法来创建,通过set方法注入属性
entity类代码如下:
public class User {
public User() {
System.out.println("User的无参构造方法");
}
private String name;
public void setName(String name) {
this.name = name;
}
public void show(){
System.out.println("name="+name);
}
}
applicationContext.xml配置:
(2)通过有参的构造方法来创建,不需要set方法
entity类
public class User {
private String name;
public User(String name) {
this.name = name;
}
public void show(){
System.out.println("name="+name);
}
}
applicationContext.xml有三种写法,一般使用第二种。
(i)
(ii)
(iii)
(3)通过工厂方法来创建对象,这种方法用的比较少。
(i)静态工厂
public class UserFactory {
public static User newInstance(String name){
return new User(name);
}
}
applicationContext.xml:
(ii)动态工厂
public class UserDynamicFactory {
public User newInstance(String name){
return new User(name);
}
}
applicationContext.xml:
使用静态工厂时,直接写上class即可,因为调用的是类方法,与对象无关。
使用动态工厂时,需要先创建工厂对象再调用方法,所以需要先bean,再factory-bean引用。
一般有Array,List,Set,Map,Props
package com.yygs.service;
public interface AccountService {
public void saveAccount();
}
package com.yygs.service.impl;
import com.yygs.service.AccountService;
import org.springframework.jdbc.core.namedparam.SqlParameterSourceUtils;
import java.util.*;
public class AccountServiceImpl implements AccountService {
private String[] myStr;
private List myList;
private Set mySet;
private Map myMap;
private Properties myProps;
@Override
public void saveAccount() {
System.out.println(Arrays.toString(myStr));
System.out.println(myList);
System.out.println(mySet);
System.out.println(myMap);
System.out.println(myProps);
}
public void setMyStr(String[] myStr) {
this.myStr = myStr;
}
public void setMyList(List myList) {
this.myList = myList;
}
public void setMySet(Set mySet) {
this.mySet = mySet;
}
public void setMyMap(Map myMap) {
this.myMap = myMap;
}
public void setMyProps(Properties myProps) {
this.myProps = myProps;
}
}
package com.yygs.ui;
import com.yygs.service.AccountService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Client {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
AccountService as = (AccountService)ac.getBean("accountService");
as.saveAccount();
}
}
AAA
BBB
CCC
AAA
BBB
CCC
AAA
BBB
CCC
Aa
@Repository 注解:描述Dao类
//组件类型注解默认beanId为类名首字母小写
//beadId = userDao
@Repository
public class UserDao implements IUserDao{
public UserDao(){
System.out.println("正在创建UserDao:" + this);
}
}
@Service 注解:描述Service业务服务类
@Service
public class DepartmentService {
@Resource
private IUserDao udao;
public void joinDepartment(){
System.out.println(udao);
}
}
@Controller 注解,描述控制类
@Controller
public class UserController {
}
@Component 注解,描述上面3种外的类,例如工具类
@Component("stringUtils")
public class StringUtils {
}
@Autowired 注解在set方法上,则自动按类型/名称对set方法参数进行注入。
@Autowired
//如果装配注解放在set方法上,则自动按类型/名称对set方法参数进行注入
public void setUdao(UserDao udao) {
System.out.println("setUdao:" + udao);
this.udao = udao;
}
@Autowired 注解在属性上,IOC容器回自动通过反射技术将属性private修饰符自动修改成public,直接进行赋值。这是在运行时动态完成的。不需要依赖set方法,因此在日常开发中,一般将@Autowired注解放在属性上,而不用编写set方法。
@Service
public class UserService {
//Spring IoC容器会自动通过反射技术将属性private修饰符自动改为public,直接进行赋值
//不再执行set方法
@Autowired
private IUserDao udao ;
public IUserDao getUdao() {
return udao;
}
}
@Autowired 注解的使用需要注意,IOC中不能有相同类型相同的2个bean,如下的UserDao以及UserOracleDao,解决办法是在某需要的类加上@Primary注解,或者去掉另一个不需要的类上的@Repository注解。
public interface IUserDao {
}
@Repository
public class UserDao implements IUserDao{
public UserDao(){
System.out.println("正在创建UserDao:" + this);
}
}
@Repository
@Primary
public class UserOracleDao implements IUserDao {
public UserOracleDao(){
System.out.println("正在创建UserOracleDao:" + this);
}
}
public class UserService {
//注入IUserDao
@Autowired
private IUserDao udao ;
public IUserDao getUdao() {
return udao;
}
}
@Resource 注解 在使用上,优先进行类名的匹配。没有匹配的类名则会进行类型进行匹配(同@Autowired)。
@Service
public class DepartmentService {
/**
* 1. @Resource设置name属性,则按name在IoC容器中将bean注入
* 2. @Resource未设置name属性
* 2.1 以属性名作为bean name在IoC容器中匹配bean,如有匹配则注入
* 2.2 按属性名未匹配,则按类型进行匹配,同@Autowired,需加入@Primary解决类型冲突
* 使用建议:在使用@Resource对象时推荐设置name或保证属性名与bean名称一致
*/
// @Resource(name = "userDao")
// private IUserDao udao;
@Resource
private IUserDao userOracledao; //规范化命名
public void joinDepartment(){
System.out.println(udao);
}
}
元数据注解一般配合配置文件。在resources目录下创建config.properties文件,文件内容为
metaData=baidu.com
connection.driver=xxxxx
connection.url=xxx
connection.username=xxx
connection.password=xxx
然后在类的属性上进行使用:
@Service
@Scope("prototype")//设置单例/多例,XML中 bean scope完全相同
public class UserService {
@Value("${metaData}")//读取config.properties的metaData属性值
private String metaData ;
@Value("${connection.password}")
private String password;
public UserService(){
System.out.println("正在创建UserService:" + this);
}
@PostConstruct //XML中bean init-method完全相同
public void init(){
System.out.println("初始化UserService对象,metaData=" + metaData);
}
}
@Configuration 标记配置类
JavaConfig实现IOC是去XML方式,通过给Bean设置@Configuration可以标记为一个配置类,相当于这个类为之前spring的xml。有这个类就可以删除之前的xml配置文件。
@Bean
将类注入IOC容器
@ComponentScan 配置扫描包路径
通过给Bean添加@ComponentScan(basePackages="com.jony"),basePackages="com.jony"就是指定扫描包的路径,相当于我们之前使用的context:component-scan
@PropertySrouce 加载外部资源文件
通过@PropertySrouce可以加载我们在resource中的资源文件,相当于我们之前使用的context:property-placeholder
1.maven工程依赖spring-test
org.springframework
spring-context
5.2.6.RELEASE
org.springframework
spring-test
5.2.6.RELEASE
junit
junit
4.12
2.利用@RunWith与@ContextConfiguration描述测试用例类
3.测试用例类从容器获取对象完成测试实例的执行
import com.imooc.spring.ioc.service.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
//将Junit4的执行权交由Spring Test,在测试用例执行前自动初始化IoC容器
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public class SpringTestor {
@Resource
private UserService userService;
@Test
public void testUserService(){
userService.createUser();
}
}