概述
轻量级
非入侵式
免费开源
控制反转(IOC)
面向切面编程(AOP)
解决企业应用开发的复杂性
Maven依赖
maven:
直接导入这一个依赖,会自动下载其他依赖
org.springframework
spring-webmvc
5.2.0.RELEASE
控制反转IOC思想
dao包下创建接口和实现类
UserDao
package com.yimin.dao;
public interface UserDao {
void getUser();//模拟获得全部用户
}
UserDaoImpl
package com.yimin.dao;
public class UserDaoImpl implements UserDao {
@Override
public void getUser() {
System.out.println("mysql:得到所有用户信息...");
}
}
UserDaoImpl2
package com.yimin.dao;
public class UserDaoImpl2 implements UserDao {
@Override
public void getUser() {
System.out.println("oracle:得到所有用户信息...");
}
}
service包下创建接口和实现类
UserService
package com.yimin.service;
public interface UserService {
void getUser();
}
UserServiceImpl
package com.yimin.service;
import com.yimin.dao.UserDao;
public class UserServiceImpl implements UserService {
private UserDao userDao;//这里不写死,使用set,将控制权转移给用户(Test)
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void getUser() {
userDao.getUser();
}
}
测试
MyTest
package com.yimin;
import com.yimin.dao.UserDaoImpl;
import com.yimin.dao.UserDaoImpl2;
import com.yimin.service.UserServiceImpl;
import org.junit.Test;
public class MyTest {
@Test
public void test(){
UserServiceImpl userService = new UserServiceImpl();
//通过set动态指定目标对象
userService.setUserDao(new UserDaoImpl());
userService.getUser();
userService.setUserDao(new UserDaoImpl2());
userService.getUser();
}
}
在service中使用set方法,实现调用时可以动态指定dao对象
用户 --> 业务层(set)--> 数据访问层
主动权:程序员 --> 用户
步骤
- 创建maven项目
- 在pojo包下新建实体类User
package com.yimin.pojo;
public class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public User(){}
public User(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
}
- resources目录下新建applicationContext.xml配置文件,通过bean创建User的对象
bean表示就是一个对象,id为对象名,class为类,property为对象属性赋值;
property为一般属性赋值时,使用value;
当属性是一个其他类的对象时,使用ref赋值,指向beans中已经配置好的对象id即可
- Test包下创建测试类,通过context获取容器中的对象
package com.yimin;
import com.yimin.pojo.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
User user1 = (User) context.getBean("user1");
System.out.println(user1.getName());
User user2 = (User) context.getBean("user2");
System.out.println(user2.getName());
}
}
这样一来,对象的创建工作就交给spring了,我们只需要从配置文件中取来用就行了;
这就是spring中的IOC思想:由主动编程改为被动接收
创建对象的方式:
spring默认采用无参构造函数创建对象
当然也可以用有参构造,使用有参构造时,使用标签constructor-arg
index是根据参数位置索引来赋值
type是根据参数类型来赋值,多个相同参数类型时,按照先后顺序对应
name是根据参数名来赋值(最形象)
其他标签
alias:别名
也可以直接在bean中使用name设置别名(可以设置多个,用逗号隔开)
import:导入spring配置文件,spring是可以有多个配置文件的,但最后只读一个
依赖注入DI
构造器注入
set注入(主要)
普通类型使用value
引用类型用ref(bean注入)
数组注入,在property中增加子标签:array,其他如list,set,map同
空值注入,value值为空即可
null注入,在property中增加子标签:
properties注入,在property中增加子标签:
扩展方式
p命名空间注入(set注入)
引入p命名空间:
xmlns:p="http://www.springframework.org/schema/p"
之后直接使用p:属性赋值:
c命名空间注入(构造器注入)
引入c命名空间:(要有有参构造函数)
xmlns:c="http://www.springframework.org/schema/c"
使用方式和p命名相似,但是使用的是构造器注入,所以要有有参构造函数
bean属性scope:作用域
singleton:单例模式(默认)
prototype:原型模式
bean自动装配
显式地使用ref
autowire属性,自动寻找beans中创建的对象,为引用类型属性赋值
值:byName,对象的id要和属性的setXXX中的XXX对应,如将Dog的id设置为dog123,则不能完成自动注入
值:byType,匹配的是属性的类型,即class。此时id可以不要,class要唯一
通过注解实现自动装配,需要在xml中添加注解的支持
@Autowired可以在属性上使用,也可以在方法上使用
package com.yimin.pojo;
import org.springframework.beans.factory.annotation.Autowired;
public class People {
private String name;
@Autowired
private Dog dog;
@Autowired
private Cat cat;
...
}
此时xml中就不用手动为Cat和Dog属性注入了,并且不需要Set方法了
@Autowired可以自动byType或byName寻找注入,首先会通过byType寻找,当有多个相同类型时,就会按byName寻找(setXXX中的XXX),否则找不到,这时可以使用@Qualifier(value="xxx"),xxx为id值,显式地指定注入对象
也可以使用@Resource注解,作用和 @Autowired相同,当按类型和按id都找不到时,可以通过@Resource(name="xxx"),xxx为id,显式地指定注入对象,同@Qualifier(value="xxx")
使用注解开发
新建一个spring项目,配置文件:
上面配置文件中指明了扫描pojo包下的@Component
注解,用来代替bean,在pojo包下创建User实体类:
package com.yimin.pojo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* 相当于bean,id为user(类名首字母小写)
*/
@Component
public class User {
//相当于property属性注入,也可以放在setter方法上
@Value("zhangsan")
public String name;
}
使用@Value进行属性注入,相当于配置文件中的
测试以及运行结果
import com.yimin.pojo.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
@Test
public void testUser(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = ctx.getBean("user", User.class);
System.out.println(user.name);
}
}
zhangsan
pojo包对应的注解为@Component
controller包对应的注解为@Controller
service包对应的注解为@Service
dao包对应的注解为@Repository
其实作用都是作为bean装配到spring容器中,名称只是为了标识每个层
作用域使用@Scope("singleton")
注解,标注在类上
使用配置类代替配置文件
pojo.User.java
package yimin.pojo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
/**
* AppConfig中每个方法的返回值就是一个bean,这里就不用添加@Component了
*/
//@Component
public class User {
@Value("zhangsan")
private String name;
public User() {
}
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
}
创建config.AppConfig.java配置类
package yimin.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import yimin.pojo.User;
@Configuration
@ComponentScan("yimin.pojo")
public class AppConfig {
@Bean
public User getUser(){
return new User();
}
}
@Configuration 表明这是一个配置类,用来代替applicationContext.xml
@ComponentScan("yimin.pojo"):扫描指定包下的@Component注解,装配到spring容器中
@Bean:标注在方法上,将方法的返回值作为bean装配到spring容器中,id默认为方法名
以上提到了两种装配情况,使用@Bean时,其实没必要为返回值相同的类标注@Configuration,若同时又加上了@Configuration,配置类上又标注了@ComponentScan("yimin.pojo"),则spring容器中就存在两个User对象了,通过user(@Component装配的对象)和getUser(@Bean装配的对象)都可以获得User对象
测试
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import yimin.config.AppConfig;
import yimin.pojo.User;
public class MyTest {
@Test
public void testUser(){
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
User user = ctx.getBean("user", User.class);
System.out.println(user.getName());
}
}
这时由于没有使用xml配置文件,不能使用
ClassPathXmlApplicationContext
,而使用AnnotationConfigApplicationContext
,参数为配置类
使用@Import()导入另一个配置类