T getBean(String name, Class extends T> clazz) throws Exception;
28 | }
29 |
--------------------------------------------------------------------------------
/demo/src/main/java/shop/stopyc/dao/impl/UserDaoImpl.java:
--------------------------------------------------------------------------------
1 | package shop.stopyc.dao.impl;
2 |
3 |
4 | import shop.stopyc.dao.UserDao;
5 |
6 | /**
7 | * @version v1.0
8 | * @ClassName: UserDaoImpl
9 | * @Description: 数据访问层实现类
10 | * @Author: YC104
11 | */
12 | public class UserDaoImpl implements UserDao {
13 |
14 | private String username;
15 | private String password;
16 |
17 | public void setUsername(String username) {
18 | this.username = username;
19 | }
20 |
21 | public void setPassword(String password) {
22 | this.password = password;
23 | }
24 |
25 | public UserDaoImpl() {
26 | System.out.println("userDao被创建了");
27 | }
28 |
29 | public void add() {
30 | System.out.println("UserDao ..." + username + "==" + password);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/demo/src/main/java/shop/stopyc/controller/UserController.java:
--------------------------------------------------------------------------------
1 | package shop.stopyc.controller;
2 |
3 |
4 | import shop.stopyc.framework.context.ApplicationContext;
5 | import shop.stopyc.framework.context.support.ClassPathXmlApplicationContext;
6 | import shop.stopyc.service.UserService;
7 |
8 | /**
9 | * @version v1.0
10 | * @ClassName: UserController
11 | * @Description: TODO(一句话描述该类的功能)
12 | * @Author: YC104
13 | */
14 | public class UserController {
15 | public static void main(String[] args) throws Exception {
16 | //1,创建spring的容器对象
17 | ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
18 | //BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
19 | //2,从容器对象中获取userService对象
20 | UserService userService = applicationContext.getBean("userService", UserService.class);
21 | //3,调用userService方法进行业务逻辑处理
22 | userService.add();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/spring-demo/src/main/java/shop/stopyc/framework/beans/PropertyValue.java:
--------------------------------------------------------------------------------
1 | package shop.stopyc.framework.beans;
2 |
3 | /**
4 | * bean被依赖的属性类
5 | *
6 | * @author YC104
7 | */
8 | public class PropertyValue {
9 |
10 | private String name;
11 | private String ref;
12 | private String value;
13 |
14 | public PropertyValue() {
15 | }
16 |
17 | public PropertyValue(String name, String ref, String value) {
18 | this.name = name;
19 | this.ref = ref;
20 | this.value = value;
21 | }
22 |
23 | public String getName() {
24 | return name;
25 | }
26 |
27 | public void setName(String name) {
28 | this.name = name;
29 | }
30 |
31 | public String getRef() {
32 | return ref;
33 | }
34 |
35 | public void setRef(String ref) {
36 | this.ref = ref;
37 | }
38 |
39 | public String getValue() {
40 | return value;
41 | }
42 |
43 | public void setValue(String value) {
44 | this.value = value;
45 | }
46 | }
--------------------------------------------------------------------------------
/spring-demo/src/main/java/shop/stopyc/framework/beans/BeanDefinition.java:
--------------------------------------------------------------------------------
1 | package shop.stopyc.framework.beans;
2 |
3 |
4 | /**
5 | * @version v1.0
6 | * @ClassName: BeanDefinition
7 | * @Description: 用来封装bean标签数据
8 | *
9 | * class属性
10 | * property子标签的数据(一些依赖的属性)
11 | * @Author: YC104
12 | */
13 | public class BeanDefinition {
14 |
15 | /**
16 | * bean唯一id
17 | */
18 | private String id;
19 | /**
20 | * 全类名
21 | */
22 | private String className;
23 |
24 | /**
25 | * property属性(bean中会有很多的依赖,这里采用集合,使用了迭代器模式)
26 | */
27 | private MutablePropertyValues propertyValues;
28 |
29 | public BeanDefinition() {
30 | propertyValues = new MutablePropertyValues();
31 | }
32 |
33 | public String getId() {
34 | return id;
35 | }
36 |
37 | public void setId(String id) {
38 | this.id = id;
39 | }
40 |
41 | public String getClassName() {
42 | return className;
43 | }
44 |
45 | public void setClassName(String className) {
46 | this.className = className;
47 | }
48 |
49 | public MutablePropertyValues getPropertyValues() {
50 | return propertyValues;
51 | }
52 |
53 | public void setPropertyValues(MutablePropertyValues propertyValues) {
54 | this.propertyValues = propertyValues;
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/spring-demo/src/main/java/shop/stopyc/framework/beans/factory/support/BeanDefinitionRegistry.java:
--------------------------------------------------------------------------------
1 | package shop.stopyc.framework.beans.factory.support;
2 |
3 |
4 | import shop.stopyc.framework.beans.BeanDefinition;
5 |
6 | /**
7 | * @version v1.0
8 | * @ClassName: BeanDefinitionRegistry
9 | * @Description: 注册表对象
10 | * @Author: YC104
11 | */
12 | public interface BeanDefinitionRegistry {
13 | /**
14 | * 注册BeanDefinition对象到注册表中
15 | * @param beanName :bean name
16 | * @param beanDefinition :bean definition
17 | */
18 | void registerBeanDefinition(String beanName, BeanDefinition beanDefinition);
19 |
20 | /**
21 | * 从注册表中删除指定名称的BeanDefinition对象
22 | * @param beanName :bean name
23 | * @throws Exception: null
24 | */
25 | void removeBeanDefinition(String beanName) throws Exception;
26 |
27 | /**
28 | * 根据名称从注册表中获取BeanDefinition对象
29 | * @param beanName: bean name
30 | * @return: BeanDefinition对象
31 | * @throws Exception: 获取不到
32 | */
33 | BeanDefinition getBeanDefinition(String beanName) throws Exception;
34 |
35 | /**
36 | * 判断注册表中是否含有该bean
37 | * @param beanName :bean name;
38 | * @return: bool
39 | */
40 | boolean containsBeanDefinition(String beanName);
41 |
42 | /**
43 | * 获取注册表中bean的数量
44 | * @return :数量
45 | */
46 | int getBeanDefinitionCount();
47 |
48 | /**
49 | * 获取注册表中所有bean的名称
50 | * @return :bean名称字符串数组
51 | */
52 | String[] getBeanDefinitionNames();
53 | }
54 |
--------------------------------------------------------------------------------
/spring-demo/src/main/java/shop/stopyc/framework/beans/factory/support/SimpleBeanDefinitionRegistry.java:
--------------------------------------------------------------------------------
1 | package shop.stopyc.framework.beans.factory.support;
2 |
3 |
4 | import shop.stopyc.framework.beans.BeanDefinition;
5 |
6 | import java.util.Map;
7 | import java.util.concurrent.ConcurrentHashMap;
8 |
9 | /**
10 | * @version v1.0
11 | * @ClassName: SimpleBeanDefinitionRegistry
12 | * @Description: 注册表接口的子实现类
13 | * @Author: YC104
14 | */
15 | public class SimpleBeanDefinitionRegistry implements BeanDefinitionRegistry {
16 |
17 | /**
18 | * 定义一个容器,用来存储BeanDefinition对象
19 | */
20 | private final Map beanDefinitionMap = new ConcurrentHashMap();
21 |
22 | public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
23 | beanDefinitionMap.put(beanName,beanDefinition);
24 | }
25 |
26 | public void removeBeanDefinition(String beanName) throws Exception {
27 | beanDefinitionMap.remove(beanName);
28 | }
29 |
30 | public BeanDefinition getBeanDefinition(String beanName) throws Exception {
31 | return beanDefinitionMap.get(beanName);
32 | }
33 |
34 | public boolean containsBeanDefinition(String beanName) {
35 | return beanDefinitionMap.containsKey(beanName);
36 | }
37 |
38 | public int getBeanDefinitionCount() {
39 | return beanDefinitionMap.size();
40 | }
41 |
42 | public String[] getBeanDefinitionNames() {
43 | return beanDefinitionMap.keySet().toArray(new String[0]);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/spring-demo/src/main/java/shop/stopyc/framework/context/support/AbstractApplicationContext.java:
--------------------------------------------------------------------------------
1 | package shop.stopyc.framework.context.support;
2 |
3 |
4 | import shop.stopyc.framework.beans.factory.support.BeanDefinitionReader;
5 | import shop.stopyc.framework.beans.factory.support.BeanDefinitionRegistry;
6 | import shop.stopyc.framework.context.ApplicationContext;
7 |
8 | import java.util.HashMap;
9 | import java.util.Map;
10 | import java.util.concurrent.ConcurrentHashMap;
11 |
12 | /**
13 | * @version v1.0
14 | * @ClassName: AbstractApplicationContext
15 | * @Description: ApplicationContext接口的子实现类,用于立即加载
16 | * @Author: 黑马程序员
17 | */
18 | public abstract class AbstractApplicationContext implements ApplicationContext {
19 |
20 | /**
21 | * 声明解析器变量
22 | */
23 | protected BeanDefinitionReader beanDefinitionReader;
24 |
25 | /**
26 | * 定义用于存储bean对象的map容器
27 | */
28 | protected Map singletonObjects = new ConcurrentHashMap();
29 |
30 | /**
31 | * 声明配置文件路径的变量
32 | */
33 | protected String configLocation;
34 |
35 | public void refresh() throws Exception {
36 | //加载BeanDefinition对象进注册表中
37 | beanDefinitionReader.loadBeanDefinitions(configLocation);
38 | //初始化bean
39 | finishBeanInitialization();
40 | }
41 |
42 | /**
43 | * bean的初始化
44 | * @throws Exception:
45 | */
46 | private void finishBeanInitialization() throws Exception {
47 | //获取注册表对象
48 | BeanDefinitionRegistry registry = beanDefinitionReader.getRegistry();
49 |
50 | //获取BeanDefinition对象
51 | String[] beanNames = registry.getBeanDefinitionNames();
52 | for (String beanName : beanNames) {
53 | //进行bean的初始化
54 | getBean(beanName);
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/spring-demo/src/main/java/shop/stopyc/framework/beans/MutablePropertyValues.java:
--------------------------------------------------------------------------------
1 | package shop.stopyc.framework.beans;
2 |
3 | import java.util.Iterator;
4 | import java.util.List;
5 | import java.util.concurrent.CopyOnWriteArrayList;
6 |
7 | /**
8 | * @version v1.0
9 | * @ClassName: MutablePropertyValues
10 | * @Description: 用户存储和管理多个PropertyValue对象(迭代器模式)
11 | * @Author: YC104
12 | */
13 | public class MutablePropertyValues implements Iterable {
14 |
15 | /**
16 | * 定义list集合对象,用来存储PropertyValue对象
17 | */
18 | private final List propertyValueList;
19 |
20 | public MutablePropertyValues() {
21 | this.propertyValueList = new CopyOnWriteArrayList();
22 | }
23 |
24 | public MutablePropertyValues(List propertyValueList) {
25 | if (propertyValueList == null) {
26 | this.propertyValueList = new CopyOnWriteArrayList();
27 | } else {
28 | this.propertyValueList = propertyValueList;
29 | }
30 | }
31 |
32 | /**
33 | * 获取所有的PropertyValue对象,返回以数组的形式
34 | * @return 集合变为数组
35 | */
36 | public PropertyValue[] getPropertyValues() {
37 | //将集合转换为数组并返回
38 | return propertyValueList.toArray(new PropertyValue[0]);
39 | }
40 |
41 | /**
42 | * 根据name属性值获取PropertyValue对象
43 | * @param propertyName :属性名称
44 | * @return :属性对象
45 | */
46 | public PropertyValue getPropertyValue(String propertyName) {
47 | //遍历集合对象
48 | for (PropertyValue propertyValue : propertyValueList) {
49 | if (propertyValue.getName().equals(propertyName)) {
50 | return propertyValue;
51 | }
52 | }
53 | return null;
54 | }
55 |
56 | /**
57 | * 判断集合是否为空
58 | * @return :true or false
59 | */
60 | public boolean isEmpty() {
61 | return propertyValueList.isEmpty();
62 | }
63 |
64 | /**
65 | * 添加PropertyValue对象
66 | * @param pv :属性对象
67 | * @return: 属性对象列表, 为了链式编程
68 | */
69 | public MutablePropertyValues addPropertyValue(PropertyValue pv) {
70 | //判断集合中存储的PropertyValue对象是否和传递进行的重复了,如果重复了,进行覆盖
71 | for (int i = 0; i < propertyValueList.size(); i++) {
72 | //获取集合中每一个PropertyValue对象
73 | PropertyValue currentPv = propertyValueList.get(i);
74 | if (currentPv.getName().equals(pv.getName())) {
75 | propertyValueList.set(i, pv);
76 | return this;
77 | }
78 | }
79 | this.propertyValueList.add(pv);
80 | return this;
81 | }
82 |
83 | /**
84 | * 判断是否有指定name属性值的对象
85 | * @param propertyName :属性名
86 | * @return :bool
87 | */
88 | public boolean contains(String propertyName) {
89 | return getPropertyValue(propertyName) != null;
90 | }
91 |
92 | /**
93 | * 获取迭代器对象
94 | * @return :迭代器对象
95 | */
96 | public Iterator iterator() {
97 | return propertyValueList.iterator();
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/spring-demo/src/main/java/shop/stopyc/framework/beans/factory/xml/XmlBeanDefinitionReader.java:
--------------------------------------------------------------------------------
1 | package shop.stopyc.framework.beans.factory.xml;
2 |
3 | import org.dom4j.Document;
4 | import org.dom4j.Element;
5 | import org.dom4j.io.SAXReader;
6 | import shop.stopyc.framework.beans.BeanDefinition;
7 | import shop.stopyc.framework.beans.MutablePropertyValues;
8 | import shop.stopyc.framework.beans.PropertyValue;
9 | import shop.stopyc.framework.beans.factory.support.BeanDefinitionReader;
10 | import shop.stopyc.framework.beans.factory.support.BeanDefinitionRegistry;
11 | import shop.stopyc.framework.beans.factory.support.SimpleBeanDefinitionRegistry;
12 |
13 | import java.io.InputStream;
14 | import java.util.List;
15 |
16 | /**
17 | * @version v1.0
18 | * @ClassName: XmlBeanDefinitionReader
19 | * @Description: 针对xml配置文件进行解析的类
20 | * @Author: YC104
21 | */
22 | public class XmlBeanDefinitionReader implements BeanDefinitionReader {
23 |
24 | /**
25 | * 声明注册表对象
26 | */
27 | private final BeanDefinitionRegistry registry;
28 |
29 | public XmlBeanDefinitionReader() {
30 | registry = new SimpleBeanDefinitionRegistry();
31 | }
32 |
33 | public BeanDefinitionRegistry getRegistry() {
34 | return registry;
35 | }
36 |
37 | public void loadBeanDefinitions(String configLocation) throws Exception {
38 | //使用dom4j进行xml配置文件的解析
39 | SAXReader reader = new SAXReader();
40 | //获取类路径下的配置文件
41 | InputStream is = XmlBeanDefinitionReader.class.getClassLoader().getResourceAsStream(configLocation);
42 | Document document = reader.read(is);
43 | //根据Document对象获取根标签对象 (beans)
44 | Element rootElement = document.getRootElement();
45 | //获取根标签下所有的bean标签对象
46 | List beanElements = rootElement.elements("bean");
47 | //遍历集合
48 | for (Element beanElement : beanElements) {
49 | //获取id属性
50 | String id = beanElement.attributeValue("id");
51 | //获取class属性
52 | String className = beanElement.attributeValue("class");
53 |
54 | //将id属性和class属性封装到BeanDefinition对象中
55 | //1,创建BeanDefinition
56 | BeanDefinition beanDefinition = new BeanDefinition();
57 | beanDefinition.setId(id);
58 | beanDefinition.setClassName(className);
59 |
60 | //创建MutablePropertyValues对象
61 | MutablePropertyValues mutablePropertyValues = new MutablePropertyValues();
62 |
63 | //获取bean标签下所有的property标签对象
64 | List propertyElements = beanElement.elements("property");
65 | for (Element propertyElement : propertyElements) {
66 | String name = propertyElement.attributeValue("name");
67 | String ref = propertyElement.attributeValue("ref");
68 | String value = propertyElement.attributeValue("value");
69 | PropertyValue propertyValue = new PropertyValue(name, ref, value);
70 | mutablePropertyValues.addPropertyValue(propertyValue);
71 | }
72 | //将mutablePropertyValues对象封装到BeanDefinition对象中
73 | beanDefinition.setPropertyValues(mutablePropertyValues);
74 |
75 | //将beanDefinition对象注册到注册表中
76 | registry.registerBeanDefinition(id, beanDefinition);
77 | }
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/spring-demo/src/main/java/shop/stopyc/framework/context/support/ClassPathXmlApplicationContext.java:
--------------------------------------------------------------------------------
1 | package shop.stopyc.framework.context.support;
2 |
3 |
4 | import shop.stopyc.framework.beans.BeanDefinition;
5 | import shop.stopyc.framework.beans.MutablePropertyValues;
6 | import shop.stopyc.framework.beans.PropertyValue;
7 | import shop.stopyc.framework.beans.factory.support.BeanDefinitionRegistry;
8 | import shop.stopyc.framework.beans.factory.xml.XmlBeanDefinitionReader;
9 | import shop.stopyc.framework.utils.StringUtils;
10 |
11 | import java.lang.reflect.Method;
12 |
13 | /**
14 | * @version v1.0
15 | * @ClassName: ClassPathXmlApplicationContext
16 | * @Description: IOC容器具体的子实现类
17 | * 用于加载类路径下的xml格式的配置文件
18 | * @Author: YC104
19 | */
20 | public class ClassPathXmlApplicationContext extends AbstractApplicationContext {
21 |
22 | public ClassPathXmlApplicationContext(String configLocation) {
23 | this.configLocation = configLocation;
24 | //构建解析器对象
25 | beanDefinitionReader = new XmlBeanDefinitionReader();
26 | try{
27 | this.refresh();
28 | } catch (Exception ignored){} {}
29 | }
30 |
31 | /**
32 | * 根据bean对象的名称获取bean对象
33 | * @param name :beanName :bean name
34 | * @return :bean对象
35 | * @throws Exception:
36 | */
37 | public Object getBean(String name) throws Exception {
38 | //判断对象容器中是否包含指定名称的bean对象,如果包含,直接返回即可,如果不包含,需要自行创建
39 | Object obj = singletonObjects.get(name);
40 | if (obj != null) {
41 | return obj;
42 | }
43 |
44 | //获取BeanDefinition对象
45 | BeanDefinitionRegistry registry = beanDefinitionReader.getRegistry();
46 | BeanDefinition beanDefinition = registry.getBeanDefinition(name);
47 | //获取bean信息中的className
48 | String className = beanDefinition.getClassName();
49 | //通过反射创建对象
50 | Class> clazz = Class.forName(className);
51 | Object beanObj = clazz.newInstance();
52 |
53 | //进行依赖注入操作
54 | MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
55 | for (PropertyValue propertyValue : propertyValues) {
56 | //获取name属性值
57 | String propertyName = propertyValue.getName();
58 | //获取value属性
59 | String value = propertyValue.getValue();
60 | //获取ref属性
61 | String ref = propertyValue.getRef();
62 | if(ref != null && !"".equals(ref)) {
63 | //获取依赖的bean对象
64 | Object bean = getBean(ref);
65 | //拼接方法名
66 | String methodName = StringUtils.getSetterMethodByFieldName(propertyName);
67 | //获取所有的方法对象
68 | Method[] methods = clazz.getMethods();
69 | for (Method method : methods) {
70 | if (methodName.equals(method.getName())) {
71 | //执行该setter方法
72 | method.invoke(beanObj,bean);
73 | }
74 | }
75 | }
76 |
77 | if(value != null && !"".equals(value)) {
78 | //拼接方法名
79 | String methodName = StringUtils.getSetterMethodByFieldName(propertyName);
80 | //获取method对象
81 | Method method = clazz.getMethod(methodName, String.class);
82 | method.invoke(beanObj,value);
83 | }
84 | }
85 |
86 | //在返回beanObj对象之前,将该对象存储到map容器中
87 | singletonObjects.put(name,beanObj);
88 | return beanObj;
89 | }
90 |
91 | public T getBean(String name, Class extends T> clazz) throws Exception {
92 | Object bean = getBean(name);
93 | if(bean == null) {
94 | return null;
95 | }
96 | return clazz.cast(bean);
97 | }
98 | }
99 |
--------------------------------------------------------------------------------