根据 【动力节点】最新Spring框架教程,全网首套Spring6教程,跟老杜从零学spring入门到高级 以及老杜的原版笔记 https://www.yuque.com/docs/share/866abad4-7106-45e7-afcd-245a733b073f?# 《Spring6》 进行整理, 文档密码:mg9b
Spring 相关文章整理汇总归纳于:https://www.yuque.com/u27599042/zuisie
/**
* ClassName: SomeService
* Package: PACKAGE_NAME
* Description:
*
* @Author tcw
* @Create 2023-05-27 10:46
* @Version 1.0
*/
public class SomeService {
public void doSome() {
System.out.println(" public void doSome() 执行");
}
public String doSome(String s) {
System.out.println(" public void doSome(String s) 执行");
return s;
}
public String doSome(String s, Integer i) {
System.out.println(" public void doSome(String s, Integer i) 执行");
return s + " " + i;
}
}
import java.lang.reflect.Method;
/**
* ClassName: Main
* Package: PACKAGE_NAME
* Description:
*
* @Author tcw
* @Create 2023-05-27 10:45
* @Version 1.0
*/
public class Main {
public static void main(String[] args) throws Exception {
// 加载类,获取类对应的Class对象
Class<?> someServiceClass = Class.forName("SomeService");
// 创建对象
// 调用类的无参构造方法创建对象
SomeService someService = (SomeService) someServiceClass.getDeclaredConstructor().newInstance();
// 获取方法 public String doSome(String s, Integer i)
// 参数一:获取方法的方法名
// 参数二:可变参数,获取方法的形参列表类型
Method doSomeMethod = someServiceClass.getDeclaredMethod("doSome", String.class, Integer.class);
// 调用方法(四要素:调用哪个对象的哪个方法,需要传递什么参数,该方法返回什么值)
// 参数一:调用哪个对象的该方法 someService
// 参数二:可变参数,调用方法需要传递的形参 "Hello World", 111
// invoke 的返回值就是调用方法的返回值 Object res
Object res = doSomeMethod.invoke(someService, "Hello World", 111);
System.out.println(res);
}
}
package cw.study.spring.pojo;
/**
* ClassName: User
* Package: cw.study.spring.pojo
* Description:
*
* @Author tcw
* @Create 2023-05-28 9:59
* @Version 1.0
*/
public class User {
private String name;
private int age;
public User() {
}
public User(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "User{" + "name='" + name + '\'' + ", age=" + age + '}';
}
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;
}
}
import cw.study.spring.pojo.User;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* ClassName: Main
* Package: PACKAGE_NAME
* Description:
*
* @Author tcw
* @Create 2023-05-27 10:45
* @Version 1.0
*/
public class Main {
public static void main(String[] args) throws Exception {
// 1.有这样一个类,类名叫做:包名.User
String className = "cw.study.spring.pojo.User";
// 2.这个类符合javabean规范。属性私有化,对外提供公开的setter和getter方法。
// 3.你还知道这个类当中有一个属性,属性的名字叫做 age
String fieldName = "age";
// 4.并且你还知道age属性的类型是int类型。
// 请使用反射机制调用set方法,给User对象的age属性赋值。
// 加载类
Class<?> userClass = Class.forName(className);
// 创建对象
User user = (User) userClass.getDeclaredConstructor().newInstance();
// 获取属性
Field field = userClass.getDeclaredField(fieldName);
// 获取属性的类型
Class<?> fieldType = field.getType();
// 获取方法名
String methodName = "set" + fieldName.toUpperCase().charAt(0) + fieldName.substring(1);
// 获取方法
Method method = userClass.getDeclaredMethod(methodName, fieldType);
// 调用方法
method.invoke(user, 22);
System.out.println(user);
}
}
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>cw.study.springgroupId>
<artifactId>spring-study-011-myspringartifactId>
<version>1.0-SNAPSHOTversion>
<packaging>jarpackaging>
<dependencies>
<dependency>
<groupId>org.dom4jgroupId>
<artifactId>dom4jartifactId>
<version>2.1.3version>
dependency>
<dependency>
<groupId>jaxengroupId>
<artifactId>jaxenartifactId>
<version>1.2.0version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.13.2version>
<scope>testscope>
dependency>
dependencies>
<properties>
<maven.compiler.source>17maven.compiler.source>
<maven.compiler.target>17maven.compiler.target>
properties>
project>
package cw.study.spring.bean;
/**
* ClassName: User
* Package: cw.study.spring.bean
* Description:
*
* @Author tcw
* @Create 2023-05-31 12:06
* @Version 1.0
*/
public class User {
private String name;
private Integer age;
public User() {
}
public void setName(String name) {
this.name = name;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User{" + "name='" + name + '\'' + ", age=" + age + '}';
}
}
package cw.study.spring.bean;
/**
* ClassName: UserDao
* Package: cw.study.spring.bean
* Description:
*
* @Author tcw
* @Create 2023-05-31 12:07
* @Version 1.0
*/
public class UserDao {
public void insert() {
System.out.println("数据库正在保存用户信息...");
}
}
package cw.study.spring.bean;
/**
* ClassName: UserService
* Package: cw.study.spring.bean
* Description:
*
* @Author tcw
* @Create 2023-05-31 14:08
* @Version 1.0
*/
public class UserService {
private UserDao userDao;
public void save() {
userDao.insert();
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
<beans>
<bean id="user" class="cw.study.spring.bean.User">
<property name="name" value="张三"/>
<property name="age" value="21"/>
bean>
<bean id="userDao" class="cw.study.spring.bean.UserDao"/>
<bean id="userService" class="cw.study.spring.bean.UserService">
<property name="userDao" ref="userDao"/>
bean>
beans>
package org.myspringframework.core;
/**
* ClassName: ApplicationContext
* Package: org.myspringframework.core
* Description:
* MySpring框架应用上下文接口
*
* @Author tcw
* @Create 2023-05-31 14:22
* @Version 1.0
*/
public interface ApplicationContext {
/**
* 通过Bean的id从容器中获取相应的Bean对象
* Bean的名称就是配置文件中Bean的id
*
* @param beanName Bean的id
* @return Bean对象
*/
Object getBean(String beanName);
}
package org.myspringframework.core;
import org.dom4j.*;
import org.dom4j.io.SAXReader;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* ClassName: ClassPathXmlApplicationContext
* Package: org.myspringframework.core
* Description:
*
* @Author tcw
* @Create 2023-05-31 14:25
* @Version 1.0
*/
public class ClassPathXmlApplicationContext implements ApplicationContext{
// 用于存放Bean对象的map集合,使用Bean的名称可以获取相应的Bean对象
private Map<String, Object> singletonObjects = new HashMap<>();
/**
* 根据Spring配置文件创建Spring容器的构造方法
* 该方法一执行就会对配置文件进行解析创建Bean对象
* 使用ClassPathXmlApplicationContext,配置文件应该放在类路径下
*
* @param configLocation Spring配置文件的路径
*/
public ClassPathXmlApplicationContext(String configLocation) {
try {
// 解析XML核心配置文件,实例化Bean,将Bean存放到map集合中
// 获取dom4j解析xml文件的核心对象,读取xml文件中的内容
SAXReader reader = new SAXReader();
// 获取xml的输入流,通过类加载器以流的方式获取资源
InputStream inputStream = ClassLoader.getSystemClassLoader().getResourceAsStream(configLocation);
// 读取xml文件中的内容,获取xml对应的文档对象
Document document = reader.read(inputStream);
// 获取xml文件中所有的bean标签
List<Node> beansNode = document.selectNodes("//bean");
// 遍历所有的bean标签,创建相应的对象放到容器中
beansNode.forEach(bean->{
try {
// System.out.println(bean);
// org.dom4j.tree.DefaultElement@74ad1f1f
// bean实际上是Element类型,向下转型,因为Element中方法更丰富
Element beanElement = (Element) bean;
// 获取Bean id
String id = beanElement.attributeValue("id");
// 获取bean的类型
String className = beanElement.attributeValue("class");
// System.out.println(id + ": " + className);
// 利用反射机制进行对象的创建,并放到map集合中,进行提前曝光
Object beanInstance = createBeanObjectByReflect(className);
// 将创建的对象放入map集合中进行曝光
singletonObjects.put(id, beanInstance);
// System.out.println(singletonObjects);
} catch (Exception e) {
e.printStackTrace();
}
});
// 再次遍历所有的bean标签,为创建的所有bean对象进行属性的赋值
beansNode.forEach(bean->{
try {
// 进行强转
Element beanElement= (Element) bean;
// 获取bean的id
String id = beanElement.attributeValue("id");
// // 判断bean是否已经被创建了
// if (!singletonObjects.containsKey(id)) {
// // 如果没有创建bean对象,则进行bean对象的创建
// Object beanInstance = createBeanObjectByReflect(className);
// }
// 获取bean的类名
String className = beanElement.attributeValue("class");
// 加载类
Class<?> clazz = Class.forName(className);
// 获取bean标签中的所有子标签属性标签
List<Element> properties = beanElement.elements("property");
// 遍历bean标签中的所有子标签属性标签,为bean的属性进行赋值
properties.forEach(property->{
try {
// 获取property标签的name属性值,获取要为哪个属性赋值
String fieldName = property.attributeValue("name");
// 获取property标签的value属性值,获取要为属性赋的值(标签中如果无value,返回null)
String fieldValue = property.attributeValue("value");
// 获取property标签的ref属性值,获取要为属性赋的值(标签中如果无ref,返回null)
String ref = property.attributeValue("ref");
// System.out.println(fieldName + " = " + fieldValue);
// 获取set方法的方法名
String setMethodName = "set" + fieldName.toUpperCase().charAt(0) + fieldName.substring(1);
// 获取set方法对应的属性的类型
Class<?> fieldType = clazz.getDeclaredField(fieldName).getType();
// 获取set方法
Method setMethod = clazz.getDeclaredMethod(setMethodName, fieldType);
// 如果属性的值是通过value进行赋值
if (fieldValue != null) {
// 值为简单类型
// 调用id对应的bean对象的set方法(set方法无返回值)
// 从标签的属性中获取的值都为字符串类型,但是set方法需要的参数有具体的数据类型,需要进行处理
// 获取set方法参数的简单类型名
String fieldTypeSimpleName = fieldType.getSimpleName();
String propertyValue = fieldValue; // 简单类型的属性值
// 进行数据类型匹配,对参数进行类型转换
Object propertyVal = null;
switch (fieldTypeSimpleName) {
case "byte": case "Byte":
propertyVal = Byte.valueOf(propertyValue);
break;
case "short": case "Short":
propertyVal = Short.valueOf(propertyValue);
break;
case "int": case "Integer":
propertyVal = Integer.valueOf(propertyValue);
break;
case "long": case "Long":
propertyVal = Long.valueOf(propertyValue);
break;
case "float": case "Float":
propertyVal = Float.valueOf(propertyValue);
break;
case "double": case "Double":
propertyVal = Double.valueOf(propertyValue);
break;
case "boolean": case "Boolean":
propertyVal = Boolean.valueOf(propertyValue);
break;
case "char": case "Character":
propertyVal = propertyValue.charAt(0);
break;
case "String":
propertyVal = propertyValue;
break;
}
// 调用id对应的bean对象的set方法(set方法无返回值)
setMethod.invoke(singletonObjects.get(id), propertyVal);
}
// 如果属性的值是通过ref进行赋值
if (ref != null) {
// 值为非简单类型
// 调用id对应的bean对象的set方法(set方法无返回值)
setMethod.invoke(singletonObjects.get(id), singletonObjects.get(ref));
}
} catch (Exception e) {
e.printStackTrace();
}
});
} catch (Exception e) {
e.printStackTrace();
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 通过反射机制进行相应类的对象的创建
*
* @param className 类的全限定类名
* @return 类的对象
* @throws Exception 异常
*/
private Object createBeanObjectByReflect(String className) throws Exception {
// 加载类
Class<?> clazz = Class.forName(className);
// 获取类的无参构造器创建对象
return clazz.getDeclaredConstructor().newInstance();
}
/**
* 根据bean的id获取bean对象
*
* @param beanName Bean的id
* @return bean对象
*/
@Override
public Object getBean(String beanName) {
return singletonObjects.get(beanName);
}
}
@org.junit.Test
public void test01() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("myspring.xml");
UserService userService = (UserService) applicationContext.getBean("userService");
userService.save();
User user = (User) applicationContext.getBean("user");
System.out.println(user);
}