概述
功能非常丰富,核心的功能是:IOC DI AOP
IOC:控制反转,就是指把创建对象的权利和对象生命周期的管理过程交给了Spring框架
DI:依赖注入,是指把对象间的依赖关系 自动维护
AOP:是面向切面编程,补充了OOP的不足
StringIOC
IOC:控制反转,就是指把创建对象的权利和对象生命周期的管理过程交给了Spring框架
重要注解
@Component//spring提供的,用来ioc,默认首字母小写的类名为Bean的名字
//自动完成IOC->{"user",new User}
//@Component("a")//指定Bean的名字--IOC->{"a",new User}
//@Controller
//@Service都是spring提供的,都可以用来ioc控制反转
测试
1.创建maven的Module--注意:导入jar包--被Spring Boot整合了,所以跳过此步骤
2.创建User类和Hello类
package com.yu.spring;
public class Hello {
public void hello(){
System.out.println("hello");
}
}
package com.yu.ioc;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
@Component//spring提供的,用来ioc,默认首字母小写的类名为Bean的名字
//自动完成IOC->{"user",new User}
//@Component("a")//指定Bean的名字--IOC->{"a",new User}
//@Controller
//@Service都是spring提供的,都可以用来ioc控制反转
public class User {
public void uesr(){
System.out.println("hello");
}
}
3.创建配置文件.xml文件:在resources文件夹下新建XML文件,配置Bean信息
<?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信息 -->
<!-- id属性:Bean的唯一标识 class属性:类的全路径-->
<!--完成IOC()->{"hello","new Hello"}-->
<bean class="com.yu.spring.Hello" id="hello"></bean>
<bean class="com.yu.spring.Student" id="student"></bean>
<!-- 配置包扫描 -->
<!-- base-package-指定包的路径 -->
<!-- 获取包下的所有带注释的Bean -->
<context:component-scan base-package="com.yu.ioc"></context:component-scan>
</beans>
4.测试SpringIOC
package com.yu.test;
import com.yu.ioc.User;
import com.yu.spring.Hello;
import com.yu.spring.Student;
import org.junit.jupiter.api.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestLOC {
@Test
public void test(){
//1.读取配置文件
ClassPathXmlApplicationContext cpa = new ClassPathXmlApplicationContext("spring-config.xml");
//2.直接getBean
Hello hello =(Hello) cpa.getBean("hello");
Student student = (Student)cpa.getBean("student");
System.out.println(hello);//com.yu.spring.Hello@6a6cb05c
hello.hello();
student.study();
User u = (User)cpa.getBean("user");
u.uesr();
}
}
SpringDI
DI:依赖注入,是指把对象间的依赖关系 自动维护
重要注释
@Autowired //相当于框架完成了:new User().setDept(new Dept());成员变量的get/set
测试
1.创建Dept类
package com.yu.di;
import org.springframework.stereotype.Component;
@Component
public class Dept {
String name = "java软件开发一部";
@Override
public String toString() {
return "Dept{" +
"name='" + name + '\'' +
'}';
}
}
2.创建Emp类
package com.yu.di;
import org.springframework.stereotype.Component;
@Component
public class Emp {
String name = "jack";
//描述两个类之间的关系
private Dept d;
public Dept getD() {
return d;
}
public void setD(Dept d) {
this.d = d;
}
@Override
public String toString() {
return "Emp{" +
"name='" + name + '\'' +
", d=" + d +
'}';
}
}
测试不使用SpringIOC的StringDI
package com.yu.testdi;
import com.yu.di.Dept;
import com.yu.di.Emp;
import org.junit.jupiter.api.Test;
public class Test01 {
@Test
public void test(){
//创建Dept对象
Dept dept = new Dept();
//创建Emp对象
Emp emp = new Emp();
System.out.println(emp);//Emp{name = 'jack', d = null}
//di--把两个对象间的关系依赖注入
emp.setD(dept);
System.out.println(emp);//Emp{name = 'jack', d = 'java软件开发一部'}
}
}
修改Emp类
package di;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Emp {
String name = "jack";
@Autowired
//@Autowired //相当于框架完成了:new User().setDept(new Dept());
Dept d;
@Override
public String toString() {
return "Emp{" +
"name='" + name + '\'' +
", d=" + d +
'}';
}
}
3.配置包扫描
<?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.tedu.di"></context:component-scan>
</beans>
4.测试
使用SpringIOC
package c.testdi;
import org.junit.jupiter.api.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestdDI {
@Test
public void test(){
ClassPathXmlApplicationContext cpa = new ClassPathXmlApplicationContext("spring-di.xml");
Object emp = cpa.getBean("emp");
System.out.println(emp);
}
}
Spring AOP
AOP面向切面编程,是一种面向切面编程的思想,补充了面向对象编程(OOP)的不足
实现的效果:对方法的增强,本质上就是在执行方法的前后添加功能
使用场景:统计性能分析,权限管理,事务管理,日志,缓存等
常用注解
@Aspect,表示是一个切面类
@Before,表示是一个前置通知
@After,表示是一个后置通知
@Around,表示是一个环绕通知
三要素
Aspect定义切面(本质上就是一个类);
通过通知(Advice)来指定具体做什么事情。如方法执行前做什么,方法执行后做什么,抛出异常做什么,从而实现对象行为(方法)的增强;
具体通过切点(PointCut)配置切点表达式(expression)来指定在哪些类的哪些方法上织入(ware)横切逻辑;被切的地方叫连接点(JoinPoint);
通知
本质上就是一个方法,有以下五种方式
前置通知before:方法执行前通知
后置通知after:方法执行后通知
环绕通知around:方法执行前后都要执行
返回后通知afterReturning
异常通知afterThrowing
步骤
1.添加jar包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>2.5.3</version>
</dependency>
2.使用
package com.yu.ServiceImpl;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Service;
@Aspect//标记着这是一个aop类:切面
@Service
public class AopAspect {
//切面由切点(指定具体要用通知的类或方法)和通知(方法的自定义功能)组成
//切点
//切点表达式: *表示1个 ..表示多个 *依次代表方法返回值,类名,方法名,(..)是参数列表
@Pointcut("execution( * com.yu.ServiceImpl..*.*(..))")
public void point(){}
//通知
@Around("point()")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable{
long begin = System.currentTimeMillis();//计时开始
//joinPoint--连接点
Object o = joinPoint.proceed();
long end = System.currentTimeMillis()-begin;//计时结束
System.out.println("方法执行时间为:"+end);
String methodname = joinPoint.getTarget().getClass().getName()//获取类名
+"."+joinPoint.getSignature().getName();//获取方法名
System.out.println("根据aop统计,"+methodname+"方法的耗时是:"+(end));
return o;
}
}