1.什么是spring
spring,就是春天的意思,。。。
spring是一个开源的轻量级Java开发框架,是一种简化应用程序的开发。
在spring出来之前,service层调用dao都是采用new对象的方法,在spring出来以后,service层和dao都会放在spring容器中去管理,这也是spring的第一种特性,我们称之为IOC,控制反装。
spring还有一种主要的特性,AOP,面向切面,说白了就是专人专事,在项目中有很多公用的模块,例如日志模块等,都可以抽调出来,这就是利用的AOP的特性。
2.spring的特性
spring主要有两大特性
IOC控制反转:DI依赖注入
AOP面向切面
3.spring组成部分
4.spring理念和核心思想
spring理念是面向Bean编程,核心思想是万物都是Bean
5.spring的优势
低侵入式的设计
独立于各种应用服务器
依赖注入将组件关系透明化,降低了耦合度
面向切面编程允许将通用任务集中处理
能够和第三方的框架良好整合
6.实现:
6.1IOC思想
在普通的设计中,在创建好service层和dao层的时候,创建对象采用的是new的方式来new出新的对象
利用spring,可以将其放在spring中,统一管理
首先:导入依赖
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.5</version>
</dependency>
然后创建service层:
public interface UserService {
Integer addUser();
}
public class UserServiceImpl implements UserService{
@Override
public Integer addUser() {
System.out.println("哈哈");
return null;
}
}
然后在resources中添加配置文件:
applicationContext.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">
<!-- id是接口名字首字母小写(公约,其他名字也行,相当于new的变量名),class实现类路径 -->
<bean id="userService" class="cn.kgc.service.UserServiceImpl"></bean>
</beans>
在测试类中:
//new一个ClassPathXmlApplicationContext对象
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//通过getBean方法获取对象
UserService userService = (UserService)ac.getBean("userService");
//调用方法
userService.add();
可以看出,此时不需要手动new出service对象,而是交给spring容器去管理
6.2spring的set注入:
spring的特性:AOP和IOC
IOC思想:控制反转,不复负责具体实现--->DI(依赖注入)
DI实现:(set注入,注解注入@,构造器注入,静态工厂注入,动态工厂注入,方法参数注入)
set注入(属性注入):对象,引用类型,属性,属性值等,又分手工注入ref和自动注入非ref(byName,byType)
6.2.1属性注入:
实体类:
public class User {
private Integer id;
private String name;
public Integer getId() {
return id;
}
public String getName() {
return name;
}
public void setId(Integer id) {
System.out.println("调用方法setId......");
this.id = id;
}
public void setName(String name) {
System.out.println("调用方法setName......");
this.name = name;
}
}
resources/applicationContext.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="user" class="cn.kgc.entity.User">
<property name="id" value="1"/>
<property name="name" value="杨幂"/>
</bean>
</beans>
测试:(在spring中getBean属性注入的时候,调用的是set方法)
@org.junit.Test
public void test(){
//实例化,主要加载地址
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//获取,需要转类型
User user = (User) ac.getBean("user");
System.out.println(user.getId());
}
最后在实现的时候,可以发现,一起调用了实体类中的set方法,同时实体类中的属性有了值
6.2.2 引用类型注入
手工注入:
创建两个实体类,User,Role
其中要有getset方法
public class User {
private Integer id;
private String name;
private Role role;
}
public class Role {
private Integer rId;
private String rName;
}
resources/applicationContext.xml:
<bean id="user" class="cn.kgc.entity.User">
<property name="id" value="1"/>
<property name="name" value="杨幂"/>
<property name="role" ref="role111"/> ref可以当作一个路径,标识,匹配下面的bean中的id
</bean>
<bean id="role111" class="cn.kgc.entity.Role">
<property name="rId" value="11"/>
<property name="rName" value="迪丽热巴"/>
</bean>
测试类:
@org.junit.Test
public void testuser(){
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User) ac.getBean("user");
System.out.println(user.getRole().getrName());
}
自动注入:
不用ref,设置自动注入:包括两种方式:btName和byType
1)byName:
实体类:
public class User {
private Integer id;
private String name;
private Role role;
}getset方法此处省略,需要添加
public class Role {
private Integer rId;
private String rName;
}
byName(按名称注入):
java类中引用类型的属性名(role)和spring容器中(配置文件)<bean>的id名称一样,
且
数据类型是一致的,这样的容器中的bean,spring能够赋值给引用类型
resources/applicationContext.xml:
<bean id="user" class="cn.kgc.entity.User" autowire="byName">
<property name="id" value="1"/>
<property name="name" value="杨幂"/>
<!-- <property name="role" ref="role"/>-->
</bean>
原先的注释掉,只要名字相同,添加btName,引用类型就能自动匹配
<bean id="role" class="cn.kgc.entity.Role">
<property name="rId" value="11"/>
<property name="rName" value="迪丽热巴"/>
</bean>
测试类:
@org.junit.Test
public void testuser(){
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User) ac.getBean("user");
System.out.println(user.getRole().getrName());
}
2)btType
byType(按类型注入):
java类中引用类型的数据类型和spring容器中(配置文件)<bean>的class属性
是同源关系的,这样的bean能够赋值给引用类型
同源就是一类型的意思:
第一种同源.java引用类型的数据类型和bean的class的值是一样的
第二种同源.java引用类型的数据类型和bean的class的值是父子类间的关系
第三种同源.java引用类型的数据类型和bean的class的值是接口和实现类的关系
第一种同源(class相同):
实体类:
public class User {
private Integer id;
private String name;
private Role role;
}getset方法此处省略,需要添加
public class Role {
private Integer rId;
private String rName;
}
xml文件:
<bean id="user" class="cn.kgc.entity.User" autowire="byType">
<property name="id" value="1"/>
<property name="name" value="杨幂"/>
</bean>
此时不需要添加id也行,同源的类,都是role属性,规约要求添加id
<bean class="cn.kgc.entity.Role">
<property name="rId" value="11"/>
<property name="rName" value="迪丽热巴"/>
</bean>
第二种同源(父子类):
public class User {
private Integer id;
private String name;
private Role role;
}getset方法此处省略,需要添加
public class Role {
private Integer rId;
private String rName;
}
public class SonRole extends Role{
}
xml文件:
<bean id="user" class="cn.kgc.entity.User" autowire="byType">
<property name="id" value="1"/>
<property name="name" value="杨幂"/>
</bean>
下面设置子类,User类中的Role可以自动获取到子类,同源
<bean class="cn.kgc.entity.SonRole">
<property name="rId" value="11"/>
<property name="rName" value="古力娜扎"/>
</bean>
第三种同源(接口):
接口类:
mapper中的两个类:接口和实现类
public interface UserMapper {
void add();
}
public class UserMapperImpl implements UserMapper {
@Override
public void add() {
System.out.println("迪丽热巴");
}
}
service中的两个类:接口和实现类
public interface UserService {
void add();
}
public class UserServiceImpl implements UserService {
private UserMapper userMapper;
public UserMapper getUserMapper() {
return userMapper;
}
public void setUserMapper(UserMapper userMapper) {
this.userMapper = userMapper;
}
@Override
public void add() {
userMapper.add();
}
}
xml:
<bean id="userService" class="cn.kgc.service.UserServiceImpl" autowire="byType"></bean>
<bean id="userMapper" class="cn.kgc.mapper.UserMapperImpl"></bean>
6.3spring的注解注入:
@Component 创建对象,等同于Bean功能
实体类:
@Data
@Component(value = "user")
public class User {
private Integer id;
private String name;
}
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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--添加一个扫描器,组件扫描器-->
<context:component-scan base-package="cn.kgc.entity"/>
</beans>
@Repository 用在持久层上面,方法在dao的实现类上面,表示创建dao对象
@Repository(value = "userMapper")
//value中的名字,是后面getBean中的方法名
public class UserMapperImpl implements UserMapper {
@Override
public Integer addUser() {
System.out.println("访问数据库。。。调用UserMapper的addUser方法......");
return null;
}
}
此时添加扫描器可以多种方式:
分号,或者多个标签,或者上级目录全部扫描
<context:component-scan base-package="cn.kgc.entity;cn.kgc.mapper"/>
或:
<context:component-scan base-package="cn.kgc.entity"/>
<context:component-scan base-package="cn.kgc.mapper"/>
或:
<context:component-scan base-package="cn.kgc"/>
@Service 用在业务层上面,放在service的实现类上面,表示创建service对象,可以有一些事务功能
@Service(value = "userService")
public class UserServiceImpl implements UserService {
@Override
public Integer addUser() {
System.out.println("调用UserService中的方法");
return null;
}
}
@Controller 在控制层,相当于servlet,添加注解
方法同上
@Value 在实体类中给简单类型的属性添加值,可以免去get set方法
@Data
@Component(value = "user")
public class User {
@Value("1")
private Integer id;
@Value("迪丽热巴")
private String name;
}
@Autowired 给引用类型属性赋值(自动装配Bean),使用,默认使用byType自动注入。
@Data
@Component(value = "user")
public class User {
@Value("1")
private Integer id;
@Value("迪丽热巴")
private String name;
@Autowired
private Role role;
}
@Data
@Component(value = "role")
public class Role {
@Value("11")
private Integer rId;
@Value("古力娜扎")
private String rName;
}
一共spring提供了上面的几种注解,每个注解用在不同的应用层。
除此之外,还有一种注解方法,不是spring提供的,是jdk中自带的:Resources
给引用类型赋值,Spring提供了对JDK注解@Resource的支持,默认按名称注入,如果按名称注入失败,自动按类型注入
使用方法和Autowired类似