上一篇:Spring:Spring简介、IOC、AOP【一】
项目地址:https://github.com/hpp3501/spring-demo
文章目录
7. Bean的自动装配
在spring中有三种装配的方式
1. 在xml中显示的配置【上一篇文章已经学习过了】
2. 在java中显示的配置
3. 隐式的自动装配Bean【重要】
7.1 测试
搭建环境: 一个人有两个宠物
cat类
package com.kuang.pojo;
public class Dog {
public void shout(){
System.out.println("汪~");
}
}
dog类
package com.kuang.pojo;
public class Cat {
public void shout(){
System.out.println("喵~");
}
}
people类
package com.kuang.pojo;
public class People {
private Cat cat;
private Dog dog;
private String name;
public Cat getCat() {
return cat;
}
public void setCat(Cat cat) {
this.cat = cat;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "People{" +
"cat=" + cat +
", dog=" + dog +
", name='" + 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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="cat" class="com.kuang.pojo.Cat"/>
<bean id="dog" class="com.kuang.pojo.Dog"/>
<bean id="people" class="com.kuang.pojo.People">
<property name="name" value="张三"/>
<property name="cat" ref="cat"/>
<property name="dog" ref="dog"/>
</bean>
</beans>
测试类
import com.kuang.pojo.People;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
@Test
public void test1() {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
People people = context.getBean("people", People.class);
people.getDog().shout();
people.getCat().shout();
}
}
打印结果
7.2 byName自动装配
autowire="byName",会自动在容器上下文中查找和自己对象set方法后面对应的bean的id;下面代码如果没有id="dog"的bean就会报错。bean的id和属性名必须相同。
7.3 byType自动装配
autowire="byType",会自动在容器上下文中查找和自己对象属性类型相同的bean;就算bean的id和属性名不相同也不会报错,只要类型相同就可以。比如下面的dog11。
小结:
- byName的时候,需要保证所有bean的id唯一,并且这个bean需要和自动注入的属性的set方法后面的值一致;
- byType的时候,需要保证所有bean的class唯一,并且这个bean需要和自动注入的属性的类型一致;
7.4 使用注解实现自动装配
要使用注解需要:
-
导入约束:context约束
xmlns:context="http://www.springframework.org/schema/context"
-
配置注解的支持
<context:annotation-config/>
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
</beans>
@AutoWired
- 默认按byType装配,当有多个类型时,可以和@Qualifier(value=“xxx”)配合使用,xxx时bean的id。
- 可以直接在属性上使用,也可以在set方法上使用。
- 使用在属性上时,可以去掉set方法。@AutoWired(required = true)等同于@AutoWired。当required =false时,代表这个属性可以为null。
配置文件改造
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!--开启注解的支持-->
<context:annotation-config/>
<bean id="cat" class="com.kuang.pojo.Cat"/>
<bean id="dog" class="com.kuang.pojo.Dog"/>
<bean id="people" class="com.kuang.pojo.People"/>
<!--
byName:会自动在容器上下文中查找和自己对象set方法后面对应的bean的id;
byType:会自动在容器上下文中查找和自己对象属性类型相同的bean;
-->
<!--<bean id="people" class="com.kuang.pojo.People" autowire="byType">-->
<!--<property name="name" value="张三"/>-->
<!--<!–<property name="cat" ref="cat"/>–>-->
<!--<!–<property name="dog" ref="dog"/>–>-->
<!--</bean>-->
</beans>
people类改造
package com.kuang.pojo;
import org.springframework.beans.factory.annotation.Autowired;
public class People {
@Autowired
private Cat cat;
@Autowired
private Dog dog;
private String name;
public Cat getCat() {
return cat;
}
// public void setCat(Cat cat) {
// this.cat = cat;
// }
public Dog getDog() {
return dog;
}
// public void setDog(Dog dog) {
// this.dog = dog;
// }
public String getName() {
return name;
}
// public void setName(String name) {
// this.name = name;
// }
@Override
public String toString() {
return "People{" +
"cat=" + cat +
", dog=" + dog +
", name='" + name + '\'' +
'}';
}
}
@Resource
- 默认按名字装配,找不到名字会按照类型装配
- 可以指定名字@Resource(name=“xxx”),xxx时bean的id
小结
@Resource和@Autowire的区别:
- 都是用来自动装配的,都可以用在属性上
- @Autowire默认通过byType实现,也可以结合@Qualifier(value=“xxx”)通过byName实现。
- @Resource默认通过byName实现,如果找不到名字则通过byType实现。
8. 使用注解开发
在Spring4之后,要使用注解开发,必须要保证aop的包导入了
需要导入context约束,增加注解的支持,这在上面已经说过了。
@Component
需要扫描包
放在类上,说明这个类被Spring容器管理了。
衍生的注解
@Component有几个衍生的注解,在web开发中会按照mvc三层架构分层。
- @Component
- dao :@Repository
- service :@Service
- controller:@Controller
以上四个注解功能都是一样的,都是代表将类注册到Spring中,装配Bean
作用域注解
@Scope(“singleton”) :单例模式
@Scope(“prototype”):原型模式
小结:
xml与注解:
xml:功能更丰富,适用于任何场合
注解:不是自己的类使用不了,维护起来比较麻烦
9. 完全使用java配置Spring
完全不使用xml配置文件,去配置Spring。全部交给java来做!
JavaConfig时Spring的一个子项目,在Spring4之后,它成为了一个核心共嗯那个。
测试
User类
package com.kuang.pojo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class User {
@Value("张三")
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
}
配置类
package com.kuang.config;
import com.kuang.pojo.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/*
@Configuration:
1.也会被Spring容器托管,因为它本身也是一个@Component
2.代表这是一个配置类,和之前的applicationContext.xml一样
*/
@Configuration
//@ComponentScan("com.kuang.config") //扫描包,只有该包下的类注解才起作用
public class KuangConfig {
@Bean //相当于xml中的bean标签
public User getUser() {
return new User();
}
}
测试类
import com.kuang.config.KuangConfig;
import com.kuang.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(KuangConfig.class);
User user = context.getBean("getUser", User.class);
System.out.println(user.getName());
}
}
输出结果
10. 代理模式
为什么要学习代理模式?因为这就是Spring AOP的底层!
代理模式的分类:
- 静态代理
- 动态代理
静态代理和动态代理视频教程
11 AOP
11.1 什么是AOP
AOP:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
11.2 AOP在Spring中的作用
提供声明式事务;允许用户自定义切面
- 横切关注点:跨越应用程序多个模块的方法或功能。就是与业务逻辑无关,但是我们需要关注的部分。比如,日志、缓存、事务、安全等。
- 切面(ASPECT):横切关注点被模块化的特殊对象。即,它是一个类。
- 通知(Advice):切面必须要完成的工作。即,它是类中的一个方法。比如,记录日志的方法。
- 目标(Target):被通知的对象。
- 代理(Proxy):向目标对象应用通知之后创建的对象。
- 切入点(PointCut):切面通知执行的“地点”的定义。
- 连接点(JoinPoint):与切入点匹配的执行点。
11.3 使用Spring实现AOP
【重点】使用AOP织入,需要导入一个依赖
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
方式一:使用Spring的接口
方式二:自定义类实现
方式三:使用注解实现
代码在【spring-09-aop】
12. 整合Mybatis
步骤:
- 导入相关jar包
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.13</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
</dependency>
</dependencies>
- 编写配置文件
- 测试
12.1 回忆Mybatis
- 编写实体类
- 编写核心配置文件
- 编写接口
- 编写Mapper.xml
- 测试
12.2 Mybatis-Spring
MyBatis-Spring 会帮助你将 MyBatis 代码无缝地整合到 Spring 中。它将允许 MyBatis 参与到 Spring 的事务管理之中,创建映射器 mapper 和 SqlSession 并注入到 bean 中,以及将 Mybatis 的异常转换为 Spring 的 DataAccessException。最终,可以做到应用代码不依赖于 MyBatis,Spring 或 MyBatis-Spring。
13. 声明式事务
13.1 事务
事务应该具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性。
- 原子性:一个事务是一个不可分割的工作单位,事务中包括的操作要么都做,要么都不做。
- 一致性:事务的执行使数据从一个状态转换为另一个状态,但是对于整个数据的完整性保持稳定。
- 隔离性:一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
- 持久性:持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
13.2 spring中的事务管理
- 声明式事务 :交给容器管理(AOP)。
- 编程式事务:需要编写代码进行事务的管理。
总结视频