Spring第一天(IOC,DI)
2017-07-17 本文已影响0人
原来蜗牛不是牛
什么是Spring
- 是进行对象管理,对象关联,解耦的一个中间层框架
- 是一个轻量级的IOC和AOP容器框架:
- 轻量级:程序实现不是很复杂,代码不是很多,占用资源不是很多,没有侵入性;
- IOC(Inversion of Control 控制反转):对象创建责任的反转(重点,核心)
- AOP(Aspect Oriented Programming):一种面向横切面编程的思想方式,可以进行功能性扩展
- 容器:可以容纳对象,并且可以控制对象的生命周期;
- 核心思想:IOC思想-控制反转,DI思想-依赖注入
耦合
回忆一下,在没有使用Spring框架时,业务层和持久层之间的调用
例:
持久层:UserDao/UserDaoImpl
业务层:UserService/UserServiceImpl
要在业务层调用持久层的方法时的做法:
public class UserServiceImpl implements UserService {
private UserDao UserDao = new UserDaoImpl();//此处即耦合了
@Override
public boolean addUser(Car car) {
return 0;
}
}
解耦
- IOC思想:创建对象的工作交给Spring管理
- DI思想:Spring创建好的对象给需要的层(类)使用
IOC开发流程
- 在maven项目的pom.xml文件中添加spring的依赖
<!-- 添加Spring包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<!-- 为了方便进行单元测试,添加spring-test包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
- 编写接口和实现类
规范要求:面向接口编程
编写LoginService接口
public interface LoginService {
void login();
}
编写LoginServiceImpl实现类
public class LoginServiceImpl implements LoginService {
@Override
public void login() {
System.out.println("登录成功!!!");
}
}
- 编写Spring的核心配置文件
在src根目录下创建applicationContext.xml文件,这就是Spring的核心配置文件
<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 definitions here -->
<!-- IOC:Spring来创建服务层对象 -->
<bean id="loginService" class="com.qf.service.LoginServiceImpl"></bean>
<!--LoginService loginService =new LoginServiceImpl()-->
</beans>
- 测试
//加载配置
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//得到指定的Bean(得到指定的对象)
LoginService loginService = (LoginService)ac.getBean("loginService");
//调用方法
loginService.login();
生命周期
Spring的生命周期在配置文件中自定义
<bean id="loginservice" class="org.cx.spring01.LoginServiceImpl" init-method="myinit" destroy-method="mydestroy" scope="prototype"></bean>
在对应类里面实现init-method="myinit" destroy-method="mydestroy"指定的方法
public void myinit(){
System.out.println("初始化方法!");
}
public void mydestroy(){
System.out.println("销毁方法!!");
}
作用域
默认创建对象的方式是单例模式
想改变创建对象的方式为多例模式,添加scope="prototype"属性
DI(依赖注入)
联想到生活中的场景:USB接口
程序中:
服务层依赖持久层
表现层依赖服务层
依赖的部分交给 Spring管理。
创建对象使用 IOC
关联使用:DI注入
依赖注入的方式
set方法注入:在类中给需要注入的属性添加setter方法
依赖的对象使用ref来关联。通过 id唯一标示进行查找
- 编写持久层DAO接口和实现类
public interface UserinfoDao {
void addUser();
void findUser();
}
public class UserinfoDaoImpl implements UserinfoDao {
public void addUser() {
// TODO Auto-generated method stub
System.out.println("addUser");
}
public void findUser() {
// TODO Auto-generated method stub
System.out.println("findUser");
}
}
- 编写服务层service接口和实现类
public interface UserinfoService {
//服务层可以暴露给其他团队使用。
//http访问不到
//其他团队可以直接使用接口
//Java开发工程师:服务端开发。
void addUser();
void findUser();
void sendMsg();
}
public class UserinfoServiceImpl implements UserinfoService {
//依赖持久层DAO
private UserinfoDAO userinfoDAO;
//依赖判断条件
//把条件做成可配置
private String tag;
private boolean execute;
//SpringDI set注入会调用这个方法
public void setUserinfoDAO(UserinfoDAO userinfoDAO) {
this.userinfoDAO = userinfoDAO;
}
public void setTag(String tag) {
this.tag = tag;
}
public void setExecute(boolean execute) {
this.execute = execute;
}
public void addUser() {
userinfoDAO.addUser();
}
public void findUser() {
userinfoDAO.findUser();
}
public void sendMsg() {
System.out.println("send.....");
//满足某种业务条件后做一次添加
userinfoDAO.addUser();
}
- 编写Spring核心配置文件
- 引入对象的注入
<!-- 1.IOC:创建持久层DAO对象,id唯一bi某个bean,某个对象-->
<bean id="userinfoDAOID" class="com.qf.dao.UserinfoDAOImpl"></bean>
<!-- 2,IOC:创建服务层service对象 -->
<bean id="userinfoService" class="com.qf.service.UserinfoServiceImpl">
<!-- 3,DI:把DAO对象注入给service使用 -->
<property name="userinfoDAO" ref="userinfoDAOID"></property>
</bean>
- 基本属性注入
<!-- 2,IOC:创建服务层service对象 -->
<bean id="userinfoService" class="com.qf.service.UserinfoServiceImpl">
<!-- 3,DI:把DAO对象注入给service使用 -->
<property name="userinfoDAO" ref="userinfoDAOID"></property>
<!-- 简单类型可以直接用value赋值 -->
<property name="tag" value="sendmsg" ></property>
<property name="execute" value="true"></property>
</bean>
构造器注入:在类中要提供带需要注入参数的构造方法
- 名称识别注入(推荐)
<constructor-arg name="tag" value="sendmail" ></constructor-arg> - 索引识别注入
<constructor-arg index="0" value="sendmail" ></constructor-arg>
集合注入
集合可以在本地内存做缓存。提高性能。
- 数组注入
<property name="ids">
<array>
<value>税源</value>
<value>赵玉磊</value>
<value>廖英杰</value>
<value>文强</value>
<value>唐蠡海</value>
</array>
</property>
- List集合注入(底层相当于一个可改变长度的数组)
<property name="list">
<array>
<value>权亮</value>
<value>余斌</value>
<value>蒋帅</value>
<value>张祎</value>
<value>邓鹏</value>
</array>
</property>
- Map注入
<property name="map">
<map>
<entry key="刘庆" value="真帅"></entry>
<entry key="陈懿" value="真棒"></entry>
<entry key="陈枭" value="就是帅"></entry>
<entry key="张岩" value="就是美"></entry>
<entry key="程波涛" value="涛涛江水"></entry>
</map>
</property>
- Set注入
<property name="set">
<set>
<value>徐可</value>
<value>朱文东</value>
<value>王家豪</value>
<value>车思韬</value>
<value>曹伟</value>
</set>
</property>
5.Properties注入
<property name="properties">
<props>
<prop key="陈潮瀚">真汉子</prop>
<prop key="陈田">小甜甜</prop>
<prop key="朱文东">小东东</prop>
<prop key="苗元">CEO</prop>
<prop key="周锐">锐锐</prop>
<prop key="曾限端">端端</prop>
<prop key="李鹏万">旺旺</prop>
</props>
</property>
回忆各种集合的遍历方式
注解
注解是Spring的配置另一种方式
持久层,业务层,表现层都可以使用注解
- 持久层替换
@Repository(value="bookDAO")//对应<bean id="bookDAO" class="com.qf.dao.BookDAOImpl"></bean>
public class BookDAOImpl implements BookDAO {
public void addBook() {
System.out.println("addBook...");
}
}
- 服务层替换
@Service(value="bookService")
public class BookServiceImpl implements BookService {
//依赖持久层:
@Autowired
@Qualifier("bookDAO")//唯一定位使用哪个DAO
private BookDAO bookDAO;
@Value(value="add")//注入属性
private String tag;
public String getTag() {
return tag;
}
public void setTag(String tag) {
this.tag = tag;
}
public void setBookDAO(BookDAO bookDAO) {
this.bookDAO = bookDAO;
}
public void addBook() {
if("add".equals(tag)){
bookDAO.addBook();
}
}
}
- Spring核心配置文件开启注解扫描
<!-- 开启注解扫描 :把包下面的所有子包下面的所有类进行扫描-->
<context:component-scan base-package="com.qf"></context:component-scan>
注解配置的方式使用在持久层和业务层会导致:
1.代码可读性差
2.依赖属性的值强编码在类中。如果修改,需要重新编译。
不适合线上操作。
所以开发中都使用注解加配置文件的方式开发:持久层和业务层使用配置文件的方式,表现层使用注解的方式