Spring FrameWork一、 前言二、IOC(控制反转)2.1 对于IOC的理解2.2如何使用IOC2.3配置文件的解读2.4IOC容器创建bean的两种方式2.5从IOC容器中取bean2.6bean的属性如
📃个人主页: 不断前进的皮卡丘
🌞博客描述: 梦想也许遥不可及,但重要的是追梦的过程,用博客记录自己的成长,记录自己一步一步向上攀登的印记
🔥网站推荐:千里之行,始于足下。每天坚持刷题,巩固所学知识,也为将来找工作,面试做好准备----- 刷题神器
文章是看楠哥的视频写的笔记
这篇博客内容把spring的基本知识点都讲到了,篇幅比较长,大家可以用于复习,也可以在学习相关知识点的时候,来看看对应内容。对于一些难点,ioc,aop等,我通过流程图,代码,文字结合来进行讲解,可以更好的理解
传统开发中,需要调用对象的时候,需要调用者手动来创建被调用者的实例,即对象是由调用者new出来的
但是在Spring框架中,创建对象的工作不再由调用者来完成,而是交给IOC容器来创建,再推送给调用者,整个流程完成反转,所以是控制反转
就比如说假设买东西,以前我们需要自己去超市买东西,但是现在我们可以不用自己去超市,我们只要把购物袋放在家门口,IOC就会自己去把我们想要的东西买回来,然后放在袋子里面,我们打开袋子拿起来用就可以了
IOC的特点是解耦合。
比如说A需要用到B,传统的开发,我们要直接创建B的实例,但是在Spring中,IOC这个容器会创建B的实例,然后把这个B注入到A
4.0.0 org.example springioc 1.0-SNAPSHOT 8 8 org.springframework spring-context 5.3.18
public class Student { private long id; private String name; private int age; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Student{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + '}'; }}
Student stu =new Student(); stu .setAge(25); stu.setId(1001); stu.setName("张三"); System.out.println(stu);
bean
标签来创建对象//读取配置文件 ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); Student stu = applicationContext.getBean("stu", Student.class); System.out.println(stu);
bean
标签来完成对象的管理id
:对象名class
:对象的模板类(所有交给IOC容器来管理的类必须要有无参构造函数,因为Spring底层是通过反射机制来创建对象,调用的是无参构造)property
标签完成赋值 name
:成员变量名value
:成员变量值(基本数据类型,String可以直接赋值,如果是其他引用类型不可以通过value赋值)ref
:把IOC中的另一个bean赋给当前成员变量(DI)无参构造函数(需要提供对应的set方法)
有参构造函数
Student stu = (Student)applicationContext.getBean("stu");
Student stu = applicationContext.getBean( Student.class);
public class Classes { private Integer id; private String name; 还有对应的get,set方法}
public class Student { private long id; private String name; private int age; private Classes classes; public Student(){ System.out.println("使用无参构造创建对象"); } public Student(long id,String name){ this.id = id; this.name = name; } public Classes getClasses() { return classes; } public void setClasses(Classes classes) { this.classes = classes; } public long getId() { return id; } public void setId(long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Student{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + ", classes=" + classes + '}'; }}
applicationContext-di.xml
bean之间的级联需要使用ref属性,而不能用value属性,否则会抛出类型转换异常
如果把学生装到班级里面,又把班级装到学生里面,就导致无限递归循环装配,最终栈溢出
bean是根据scope来生成的,表示bean的作用域,scope有4种类型
singleton,单例,表示通过Spring容器获取的对象是唯一的,是默认值
prototype,原型,表示通过Spring容器获取的对象是不同的
Spring中的继承不同于Java中的继承
Java中的继承是针对于类的
Spring中的继承是针对于对象(bean)
jdbc.properties
user=rootpassWord=rooturl=jdbc:Mysql://localhost:3306/springdriverName=com.mysql.cj.jdbc.Driver
spring-properties.xml
IOC通过工厂模式创建bean有两种方式:
public class Car { private Integer num; private String brand; public Car() { } public Car(Integer num, String brand) { this.num = num; this.brand = brand; } public Integer getNum() { return num; } public void setNum(Integer num) { this.num = num; } public String getBrand() { return brand; } public void setBrand(String brand) { this.brand = brand; } @Override public String toString() { return "Car{" + "num=" + num + ", brand='" + brand + '\'' + '}'; }}
public class StaticCarFactory { private static Map carMap; static { carMap = new HashMap<>(); carMap.put(1, new Car(1, "奥迪")); carMap.put(2, new Car(2,"奥拓")); } public static Car getCar(Integer num ){ return carMap.get(num); }}
public class InstanceCarFactory { private Map carMap; public InstanceCarFactory() { carMap = new HashMap<>(); carMap.put(1, new Car(1, "奥迪")); carMap.put(2, new Car(2, "奥拓")); } public Car getCar(Integer num){ return carMap.get(num); }}
区别:
byName的操作如下:
public class Person { private Integer id; private String name; private Car car; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Car getCar() { return car; } public void setCar(Car car) { this.car = car; } @Override public String toString() { return "Person{" + "id=" + id + ", name='" + name + '\'' + ", car=" + car + '}'; }}
注:如果bean的id有多个一致的,会报错,如Bean name 'car' is already used in this
byType的操作如下:
使用byType进行自动装配的时候,必须保证IOC中有且只有一个符合,如果有多个符合,则报下面的异常:
Spring IOC的作用是帮助开发者创建项目中所需要的bean,同时完成bean之间的依赖注入关系,DI
实现该功能有两种方式:
@Component(value="repository")public class Repository { private DataSource dataSource; public DataSource getDataSource() { return dataSource; } public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } @Override public String toString() { return "Repository{" + "dataSource=" + dataSource + '}'; }}
DI
注解默认的beanid是类名以小写开头,我们可以通过value来设置
如果我们想要把datasource也注入进来需要怎么做呢?
首先我们要把DataSource先扫进来
@Componentpublic class Repository { @Autowired private DataSource dataSource; public DataSource getDataSource() { return dataSource; } public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } @Override public String toString() { return "Repository{" + "dataSource=" + dataSource + '}'; }}
@Componentpublic class Repository { @Autowired @Qualifier(value = "datasource") private DataSource dataSource; public DataSource getDataSource() { return dataSource; } public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } @Override public String toString() { return "Repository{" + "dataSource=" + dataSource + '}'; }}
这表明把IOC中id为datasource的bean注入到repository中
实体类中普通的成员变量(String,包装类等),可以通过@Value注解来赋值
@Componentpublic class DataSource { @Value("root") private String username; @Value("123456") private String password; @Value("jdbc:mysql://localhost:3306/spring") private String url; @Value("com.mysql.cj.jdbc.Driver") private String driveName; }
实际开发中我们会把程序分成三层:
通过一个例子来理解AOP。
public interface Cal { public int add(int num1,int num2); public int sub(int num1,int num2); public int mul(int num1,int num2); public int div(int num1,int num2);}
public class CalImpl implements Cal { @Override public int add(int num1, int num2) { int res = num1 + num2; return res; } @Override public int sub(int num1, int num2) { int res = num1 - num2; return res; } @Override public int mul(int num1, int num2) { int res = num1 * num2; return res; } @Override public int div(int num1, int num2) { int res=num1/num2; return res; }}
日志打印
对于计算器来说,加减乘除就是业务代码,日志打印就是非业务代码
AOP如何实现? 使用动态代理的方式来实现
代理首先要具备CalImpl的所有功能(实现同一个接口),并且在这个基础上,扩展出打印日志的功能
public class MyInvocationHandler implements InvocationHandler { //委托对象 private Object object = null; //返回代理对象 public Object bind(Object object) { this.object = object; return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(),this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //实现业务代码和非业务代码的解耦合 System.out.println(method.getName()+"方法的参数是:"+ Arrays.toString(args)); Object res = method.invoke(this.object, args); System.out.println(method.getName()+"方法的结果是:"+res); return res; }}
上述代码通过动态代理机制实现了业务代码和非业务代码的解耦合,这是Spring AOP的底层实现机制,真正使用 Spring AOP进行开发的时候,不需要这么复杂
Spring AOP的开发步骤
@Component@Aspectpublic class LoggerAspect { @Before("execution(public int com.zyh.aop.impl.CalImpl.*(..))") public void before(JoinPoint joinPoint) { String name = joinPoint.getSignature().getName(); Object[] args = joinPoint.getArgs(); System.out.println(name + "方法的参数是:" + Arrays.toString(args)); } @After("execution(* com.zyh.aop.impl.CalImpl.*(..))") public void after(JoinPoint joinPoint){ String name = joinPoint.getSignature().getName(); System.out.println(name+"方法执行完毕"); } @AfterReturning(value = "execution(* com.zyh.aop.impl.CalImpl.*(..))",returning = "rs") public void afterReturning(JoinPoint joinPoint,Object rs){ String name = joinPoint.getSignature().getName(); System.out.println(name+"方法执行的结果是:"+rs); }@AfterThrowing(value = "execution(* com.zyh.aop.impl.CalImpl.*(..))",throwing = "ex") public void afterThrowing(JoinPoint joinPoint,Exception ex){ String name = joinPoint.getSignature().getName(); System.out.println(name+"方法抛出异常"+ex);}}
@Componentpublic class CalcImpl implements Calc{ @Override public int add(int a, int b) { int result=a+b; return result; } @Override public int sub(int a, int b) { int result=a-b; return result; } @Override public int mul(int a, int b) { int result= a*b; return result; } @Override public int div(int a, int b) { int result= a/b; return result; }}
spring-aop.xml
测试
AOP的概念
来源地址:https://blog.csdn.net/qq_52797170/article/details/125549416
--结束END--
本文标题: Spring全面详解(学习总结)
本文链接: https://lsjlt.com/news/371594.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-04-01
2024-04-03
2024-04-03
2024-01-21
2024-01-21
2024-01-21
2024-01-21
2023-12-23
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0