spring IOC (Inversion of Control,控制反转)
从这一小节开始,我们进入spring的学习
在学习之前我把之前所有的代码都共享出来,方便大家学习 探讨。
代码地址:
https://gitee.com/cgyspace/code-demos
选用的spring版本: 5.2.13.RELEASE
基于xml配置方式
-
先创建几个java类
package com.cgy.spring5.ioc.entity; public class User { private String userName; private String password; public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
package com.cgy.demos.spring5.ioc.dao; import com.cgy.demos.spring5.ioc.entity.User; public class UserDao { public User getUserByName(String userName){ User user = new User(); user.setUserName(userName); user.setPassword("123456"); return user; } }
package com.cgy.spring5.ioc.service; import com.cgy.demos.spring5.ioc.dao.UserDao; import com.cgy.demos.spring5.ioc.entity.User; public class UserService { private UserDao userDao; public User getUserByName(String userName){ return userDao.getUserByName(userName); } public void setUserDao(UserDao userDao) { this.userDao = userDao; } }
package com.cgy.spring5.ioc.service; import com.cgy.demos.spring5.ioc.entity.User; public class LoginService { public String login(User user){ if (user!=null&& user.getUserName()!=null){ return user.getUserName() + "登录成功"; } return "登录失败"; } }
这里准备了两个service 和一个dao 还有一个实体类 User
在resources目录下创建context.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
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="loginService" class="com.cgy.spring5.ioc.service.LoginService">
</bean>
<bean name="userService" class="com.cgy.spring5.ioc.service.UserService">
<property name="userDao" ref="userDao"></property>
</bean>
<bean name="userDao" class="com.cgy.spring5.ioc.dao.UserDao">
</bean>
</beans>
创建测试类
package com.cgy.spring5.ioc;
import com.alibaba.fastjson.JSON;
import com.cgy.spring5.ioc.entity.User;
import com.cgy.spring5.ioc.service.LoginService;
import com.cgy.spring5.ioc.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("context.xml");
UserService userService = context.getBean(UserService.class);
LoginService loginService = (LoginService) context.getBean("loginService");
User user = userService.getUserByName("张三");
System.out.println(JSON.toJSONString(user));
System.out.println(loginService);
}
}
查看输出结果
几点说明: 用这种方式注入的 需要有setter方法,如果没有的话会报错。后面讲DI的时候也会说到
ApplicationContext context = new ClassPathXmlApplicationContext(“context.xml”); 这里的context.xml默认是classpath 目录下,如果改其他地方,请指定清楚,不然会找不到配置文件
静态工厂创建
<bean name="clientService" class="com.cgy.spring5.ioc.service.ClientService"
factory-method="getInstance" > <!-- 这里必须是静态工厂方法 -->
</bean>
package com.cgy.spring5.ioc.service;
public class ClientService {
private String mark = "ClientService";
private static ClientService clientService = new ClientService();
private ClientService(){
}
public static ClientService getInstance(){
return clientService;
}
public String getMark() {
return mark;
}
public void setMark(String mark) {
this.mark = mark;
}
}
加入入参的静态工厂
<?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 name="clientService" class="com.cgy.spring5.ioc.service.ClientService" factory-method="getInstance">
<constructor-arg type="java.lang.String" value="测试输入参数"></constructor-arg>
</bean>
package com.cgy.spring5.ioc.service;
public class ClientService {
private static ClientService clientService = new ClientService();
private ClientService(){
}
public static ClientService getInstance(String mark){
System.out.println(mark);
return clientService;
}
}
工厂方法创建多个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 name="serviceFactory" class="com.cgy.spring5.ioc.service.ServiceFactory">
</bean>
<bean name="userService" factory-bean="serviceFactory" factory-method= "getUserService"> <!--这里不能是静态方法-->
</bean>
<bean name="loginService" factory-bean="serviceFactory" factory-method= "getLoginService">
</bean>
</beans>
package com.cgy.spring5.ioc.service;
public class ServiceFactory {
private static LoginService loginService = new LoginService();
private static UserService userService = new UserService();
public LoginService getLoginService(){
return loginService;
}
public UserService getUserService(){
return userService;
}
}
加入参数的工厂方法
<?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 name="serviceFactory" class="com.cgy.spring5.ioc.service.ServiceFactory">
</bean>
<bean name="userService" factory-bean="serviceFactory" factory-method= "getUserService"> <!--这里不能是静态方法-->
<constructor-arg type="java.lang.String" value="这是一个标记"/>
</bean>
<bean name="loginService" factory-bean="serviceFactory" factory-method= "getLoginService">
<constructor-arg type="java.lang.String" value="这是另一个标记"/>
</bean>
</beans>
package com.cgy.spring5.ioc.service;
public class ServiceFactory {
private static LoginService loginService = new LoginService();
private static UserService userService = new UserService();
public LoginService getLoginService(String mark){
System.out.println(mark);
return loginService;
}
public UserService getUserService(String mark){
System.out.println(mark);
return userService;
}
}
说明:
这里的 factory-method 只会在context 初始化的时候调用一次,并把获取到的bean 放入容器中,如果你下次再获取这个bean 依然容器中创建好的同一个bean