1 修改服务器的端口号
1.1 在resources里创建application.yml文件
#语法规则比较严谨k: v,修改端口号8080(1025~65535)
server:
port: 8888
1.2 测试
端口号已经不再是8080了
http://localhost:8888/hello/show
2 IOC的xml方式
2.1 创建配置文件spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--suppress SpringFacetInspection -->
<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">
<!--
spring认为万物都是bean,只要你的类,交给spring框架,spring就能IOC
IOC是控制反转:是指Spring框架会帮你创建对象,你来获取对象
id属性是每个bean标签的唯一标识,class属性是用来指定类的全路径
IOC底层Map的数据结构
{"hello",Class.forName("cn.tedu.spring.Hello").newInstance()}
scope="prototype" 可以设置bean对象是单例的还是多例的,默认是singleton是单例的
-->
<bean id="hello" class="cn.tedu.spring.Hello"></bean>
<!--IOC:底层就是Map结构,key是id的值,value是根据class的值反射创建的对象
{"student",Class.forName("cn.tedu.spring.Student").newInstance() }
-->
<bean id="student" class="cn.tedu.spring.Student"></bean>
</beans>
2.2 创建测试类
package cn.tedu.ioc;
import cn.tedu.spring.Hello;
import cn.tedu.spring.Student;
import org.junit.jupiter.api.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test1 {
//junit单元测试方法:测试一段代码的结果@Test
@Test
public void get(){
//1,读取配置文件--参数是配置文件的名字
ClassPathXmlApplicationContext spring =
new ClassPathXmlApplicationContext(
"spring.xml");
//2,获取对象--参数是配置文件里,bean标签的id的属性值
Object o = spring.getBean("hello");
//cn.tedu.spring.Hello@4550bb58
System.out.println(o);
Hello h = (Hello) o;//向下转型--使用子类自己的资源
h.show();
Object o2 = spring.getBean("hello");
//cn.tedu.spring.Hello@4550bb58
System.out.println(o2);//地址值
Object o3 = spring.getBean("student");
System.out.println(o3);//cn.tedu.spring.Student@38425407
Student s = (Student)o3;//向下转型
s.add();
}
}
3 IOC的注解方式
常用的IOC注解有四个: 功能都一样,都是交给spring框架创建对象
- @controller控制器(注入服务),用于标注控制层组件
- @service服务(注入dao),用于标注业务层组件
- @repository 实现dao访问,用于标注数据访问组件,即DAO组件
- @component 把普通pojo实例化到spring容器中,相当于配置文件中的,泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注,一般用于标注配置类组件
3.1 定义类 使用注解@Component
package cn.tedu.spring;
import org.springframework.stereotype.Component;
@Component//IOC,让spring去new
public class Order {
public void save(){
System.out.println(1000);
}
}
3.2 配置包扫描:指定扫描的包的名字
<?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">
<!--用包扫描的机制,代替以前bean标签的配置
IOC的本质是底层创建一个Map集合{类名的首字母变小写,类的对象}
区别:以前一个类必须配置对应的bean标签,
现在是只要在扫描的范围内而且使用了IOC注解的spring都会new
base-package:指定包的路径
包扫描的范围要适当的控制,范围越小扫描的速度越快
-->
<context:component-scan base-package="cn.tedu.spring"></context:component-scan>
</beans>
3.3 测试
package cn.tedu.ioc;
import org.junit.jupiter.api.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test1 {
@Test
public void get(){
//1,读取配置文件
ClassPathXmlApplicationContext spring =
new ClassPathXmlApplicationContext(
"spring.xml");
//2,直接getBean
Object o = spring.getBean("order");
System.out.println(o);//cn.tedu.spring.Order@26275bef
Object o2 = spring.getBean("order");
System.out.println(o2);
}
}
3.4 总结
- 创建类, 并且一定要使用IOC注解(@Component @Controller @Service @Repository)
- 配置包扫描, 需要指定包的路径, 包的扫描范围越小越好, 合理的定范围就可以
- IOC本质就是, 把你创建的类,Spring框架创建对象,存入Map集合里.
key是类名(首字母小写) value是类的对象(框架利用反射来创建的对象)
Map -> { “hello” , Class.forName(“Hello类的全路径”).newInstance() }
4 DI依赖注入
4.1 创建Dept类
package cn.tedu.spring;
import org.springframework.stereotype.Component;
@Component
public class Dept {
String name="java开发部";
@Override
public String toString() {
return "Dept{" +
"name='" + name + '\'' +
'}';
}
}
4.2 创建User类
package cn.tedu.spring;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class User {
//1,想要表示两个类之间的依赖关系:DI--把对方当做成员变量
@Autowired //依赖注入/自动装配/自动布线
Dept dept;
String name="jack";
@Override
public String toString() {
//2,使用了依赖的对象的属性或者方法
System.out.println(dept.name);
dept.toString();
return "User{" +
"dept=" + dept +
", name='" + name + '\'' +
'}';
}
}
4.3 总结
- 什么时候需要IOC?
需要把创建对象的权利交给Spring框架管理时 - 什么时候需要DI?
当A类想用B类的属性或者方法时,直接把B类依赖注入到A类就可以
@Component
class A{
@Autowired //di注解,前提是先完成IOC
B b ;
}
@Component
class B{ }
- DI的前提是完成IOC
5 AOP
5.1 概述
是面向切面编程的思想.好处是: 把一些共性代码,提取形成切面,提供丰富的通知,聚焦了程序员的关注点,只关注业务本身.
- 切面Aspect: 就是一个类
- 通知Advice: 类里的方法,分类:
前置通知, 是指调用业务方法前会被执行的功能(适用于权限管理,缓存管理)
后置通知, 是指调用业务方法后会被执行的功能(适用于释放资源)
环绕通知, 是指调用业务方法的前 后 会被执行的功能(适用于事务管理,性能分析)
返回后通知, 是指调用业务方法并返回了结果后 会被执行的功能
异常通知, 是指调用业务方法并抛出异常后 会被执行的功能 - 切点PointCut: 触发通知执行的那个方法的时间点
5.2 使用步骤
- 添加jar包的坐标(直接在Project的pom.xml里加)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
- 创建切面和通知
5.3 测试
需求:统计每个方法的性能
OOP
package cn.tedu.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("time")
public class TimeController {
//TODO 提供丰富的方法,并统计性能
@RequestMapping("get")
public void get(){
long time = System.currentTimeMillis();//计时开始
for (int i = 0; i < 1000; i++) {
System.out.print(i);
}
long end = System.currentTimeMillis();//计时结束
System.out.println();
System.out.println(end-time);//性能
}
@RequestMapping("find")
public void find(){
long time = System.currentTimeMillis();//计时开始
for (int i = 0; i < 10000; i++) {
System.out.print(i);
}
long end = System.currentTimeMillis();//计时结束
System.out.println();
System.out.println(end-time);//性能
}
}
AOP
问题: 每个方法都想统计性能,性能统计的代码需求写好多次.
解决方案:利用AOP,提取共性代码形成切面,并提供通知
package cn.tedu.spring;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Component //ioc的注解,交给spring完成new
@Aspect//spring整合了aspectj提供了面向切面编程的方式
//切面就是一个类,由通知(就是方法) 和 切点组成
public class TimerAspect {
//切点:什么时候要触发通知的功能
//方法返回值 包名 类名 方法名(参数列表)
@Pointcut("execution(* cn.tedu.controller.*.*(..))")
public void pointcut(){}
//这是前置通知,在调用目标方法前 触发执行
@Before("pointcut()")
public void beforeMethod(JoinPoint joinPoint){
//TODO 检查缓存,权限,日志
System.out.println("我是前置通知~~~");
}
//这是后置通知,在调用目标方法后 触发执行
@After("pointcut()")
public void afterMethod(JoinPoint joinPoint){
//TODO 关流 ...
System.out.println("我是 后置通知~~~");
}
//这是环绕通知,在调用目标方法前后 触发执行
@Around("pointcut()")
public Object aroundMethod(ProceedingJoinPoint joinPoint)
throws Throwable {
//TODO 事务管理 性能分析 日志管理
//统计每个方法的执行性能
long start = System.currentTimeMillis();//计时开始
Object o = joinPoint.proceed();//找到目标方法并执行
long end = System.currentTimeMillis(); //计时结束
System.out.println("aop统计的结果表示,方法的耗时是:"+(end-start));
return o ;//放行,执行目标方法
}
}
测试AOP
就是打开浏览器,访问Controller层的各种方法,都会触发执行通知的功能.观察IDEA里控制台的输出语句就知道了.
http://localhost:8080/time/find
http://localhost:8080/time/get
6 Git的日常操作
上传
- 把即将上传的资料,考到你Git的本地仓库
- 在本地仓库,执行以下Git命令:
git add .
git commit -m “test”
git push -u origin master
下载
git clone https://gitee.com/cgblpx/cgb210801.git