springDI依赖注入思想
spring创建对象的几种形式
创建一个maven项目,导入jar包还是昨天的jar包
spring-context-***.jar
spring-context-support-***.jar
commons-logging
创建resources目录,在目录中创建applicationContext.xml
创建包的包结构
controller
dao
——Impl
pojo
service
——Impl
utils
在pojo包中创建一个user实体类
public class User {
private int id;
private String username;
private String password;
public User() {
System.out.println("无参构造");
}
public User(int id, String username, String password) {
System.out.println("有参构造");
this.id = id;
this.username = username;
this.password = password;
}
无参构造创建对象
<bean id="user" class="com.lanou.pojo.User">
<!--利用setter方法赋值-->
<property name="id" value="1"></property>
<property name="username" value="我是警察"></property>
<property name="password" value="12345"></property>
</bean>
有参构造创建对象
通过name注入 通过type注入,通过index注入
<bean id="user" class="com.lanou.pojo.User" scope="singleton" lazy-init="true">
<!--有参构造方法给对象赋值-->
<constructor-arg name="id" value="123" type="int"></constructor-arg>
<constructor-arg name="username" value="说爱你" type="java.lang.String"></constructor-arg>
<constructor-arg name="password" value="love" type="java.lang.String"></constructor-arg>
<!--<constructor-arg index="0" value="121"></constructor-arg>
<constructor-arg index="1" value="我爱你"></constructor-arg>
<constructor-arg index="2" value="sss"></constructor-arg>-->
</bean>
在测试类进行测试,testIOC()方法如下
@Test
public void testIOC(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = context.getBean(User.class);
System.out.println(user.toString());
}
静态工厂
非静态工厂
复杂数据类型的注入
TestCollection类
public class TestCollection {
private User user;
private Object[] array;
private List<Object> list;
private Map<String,Object> map;
private Properties properties;
//setter getter 无参 有参 toString
}
在xml中配置复杂类型
<bean id="testCollection" class="com.lanou.pojo.TestCollection">
<!--对象类型 ref引入参照对象-->
<property name="user" ref="user"></property>
<!--数组-->
<property name="array">
<list>
<value>郑州</value>
<value>123</value>
<value>0.12</value>
</list>
</property>
<!--集合类型list-->
<property name="list">
<list>
<value>郑州</value>
<value>洛阳</value>
<value>开封</value>
</list>
</property>
<!--集合类型map-->
<property name="map">
<map>
<entry key="area" value="河南"></entry>
<entry key="fruit" value="芒果"></entry>
<entry key="user" value-ref="user"></entry>
</map>
</property>
<!--Properties类型赋值 key=value-->
<property name="properties">
<props>
<prop key="driver">com.mysql.jdbc.Driver</prop>
<prop key="url">jdbc:mysql://localhost/mybatis</prop>
<prop key="username">root</prop>
<prop key="password">123456</prop>
</props>
</property>
</bean>
在测试类中进行测试
@Test
public void testCollection(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
TestCollection testCollection = context.getBean(TestCollection.class);
System.out.println(testCollection.toString());
}
spring注解模式
引入jar包。aopjar包的版本号要和之前的保持一致
spring-aop.jar
注意:要把junit的jar包版本改为4.12或以上版本不然会报
Caused by: java.lang.IllegalStateException: SpringJUnit4ClassRunner requires JUnit 4.12 or higher.
步骤一:在配置文件xml配置文件中
<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">
<!--可省略不写 开启spring注解功能-->
<context:annotation-config></context:annotation-config>
<!--定义注解扫描的包-->
<context:component-scan base-package="com.lanou"></context:component-scan>
</context:component-scan>
</beans>
开启注解功能后在可以把user的bean配置都注解掉可以对user做如下的配置
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component(value = "user")
public class User {
@Value(value = "123")
private int id;
@Value("张三")
private String username;
@Value("123456")
private String password;
//....
}
再运行上面的testIOC()测试方法。也可以看到结果。user中的结果。
spring注解模式
目的:比如采用注解从controller层通过service层调用dao层的方法
1.控制层中的UserController
import com.lanou.pojo.User;
import com.lanou.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import java.util.List;
@Controller(value = "userController")
@Scope("prototype")//多例模式
public class UserController {
// 之前是这样调用的
// private UserService userService = new UserServiceImpl();
//属性
@Autowired
private UserService userService;
public void findAll(){
List<User> list = userService.findAll();
System.out.println(list.toString());
}
}
2.在service层中创建UserService接口
import com.lanou.pojo.User;
import java.util.List;
public interface UserService {
public List<User> findAll();
}
3.然后再Impl包中创建UserServiceImpl的实现类
import com.lanou.dao.UserDao;
import com.lanou.pojo.User;
import com.lanou.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
@Service("userService")
public class UserServiceImpl implements UserService {
//对象属性注入值
@Autowired //既可以通过类型,也可以通过名称注入
private UserDao userDao;
@Override
public List<User> findAll() {
return userDao.findAll();
}
}
4.在dao层中创建UserDao的接口
import java.util.List;
public interface UserDao {
public List<User> findAll();
}
5.在dao层的实现类中实现dao层的接口
import org.springframework.stereotype.Repository;
import java.util.ArrayList;
import java.util.List;
@Repository("userDao")
public class UserDaoImpl implements UserDao {
@Override
public List<User> findAll() {
//模拟数据
User user = new User(1,"张三","12354");
List list = new ArrayList();
list.add(user);
return list;
}
}
测试方法
@Test
public void testControllerDI(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserController userController = context.getBean("userController", UserController.class);
//UserController userController2 = context.getBean("userController", UserController.class);
//System.out.println(userController == userController2);//为了测试单例模式和多例模式是否有效
userController.findAll();
}
可以走的通说明不用在配置文件中配置,注解模式就可以走通。
如果dao层中一个接口下有两个实现类呢?改找那个呢
那么问题来了,如果dao层有两个dao的实现类呢?肯定是会报错,但如何来解决呢?
有两种方式解决:
对象属性注入值
@Autowired 既可以通过类型,也可以通过名称注入
@Qualifier(value = “userDao2”) 两个注解联合使用时,强制指定通过名称注入
二
@Resource(name = “userDao2”)
可以在dao的实现类中
跟daoImpl中代码一样
import org.springframework.stereotype.Repository;
import java.util.ArrayList;
import java.util.List;
@Repository("userDao2")
public class UserDaoImpl2 implements UserDao {
@Override
public List<User> findAll() {
//模拟数据
User user = new User(2,"张三2","123542");
List list = new ArrayList();
list.add(user);
return list;
}
}
在service层实现类中加入
@Service("userService")
public class UserServiceImpl implements UserService {
/* //对象属性注入值
@Autowired //既可以通过类型,也可以通过名称注入
@Qualifier(value = "userDao2")// 两个注解联合使用时,强制指定通过名称注入*/
//方式二:
@Resource(name = "userDao2")
private UserDao userDao;
//.... 下面代码跟上面的一样
在测试类中在运行一遍方法,可以走通,走的是张三2
测试方法前使用注解简化代码
比如
在测试类上配置相关的注解可以看到也能走的通获取到dao层模拟的数据,
说明注解这就成功了
import com.lanou.controller.UserController;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
//创建sprng容器
@RunWith(SpringJUnit4ClassRunner.class)
//指定配置文件位置
@ContextConfiguration("classpath:applicationContext.xml")
public class TestSpringJunit {
@Autowired
private UserController userController;
@Test
public void test(){
userController.findAll();
}
}