模拟Spring

1 篇文章 0 订阅

模拟IOC

在这里插入图片描述

  • BeanFactory
package org.spring.util;

import com.luban.service.UserService;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.*;

public class BeanFactory {
    /**
     *
     */
    Map<String, Object> map = new HashMap<String, Object>();

    public BeanFactory(String xml) {
        parseXml(xml);
    }

    public void parseXml(String xml) {
        File file = new File(this.getClass().getResource("/").getPath() + "//" + xml);
        SAXReader reader = new SAXReader();
        try {
            Document document = reader.read(file);
            Element root = document.getRootElement();
//            List<Element> allChild = root.elements();
            Attribute default_autowire = root.attribute("default-autowire");
            boolean flag = false;
            //判断根据什么自动装配,若为空,则说明是根据byName
            if (default_autowire != null) {
                //不为空
                flag = true;
            }
//            第一层Bean
            for (Iterator<Element> itFirst = root.elementIterator(); itFirst.hasNext(); ) {
                /**
                 * 第一步。实例化对象
                 */
                Element elementFirstChild = itFirst.next();
                Attribute attributeID = elementFirstChild.attribute("id"); //属性,beanName
                String beanName = attributeID.getValue();
                Attribute attributeClass = elementFirstChild.attribute("class");//获取全类名,具体的类
                String className = attributeClass.getValue();

                Class<?> classzz = Class.forName(className);//获取类对象


                /**
                 * 维护依赖关系
                 * 看这个对象有没有依赖(判断是否有有property, 或者判断类是否有属性)
                 * 就是给类对象中注入值
                 */
                //第二层,依赖关系
                Object object = null;//实例化对象的变量,判断是否有依赖在进行实例化
                for (Iterator<Element> itSecond = elementFirstChild.elementIterator(); itSecond.hasNext(); ) {
                    /**
                     * <property name="dao" ref="dao"></property>
                     * 得到ref的value,通过value得到对象(map)
                     * 得到的name的值,然后根据值获取一个Filed的对象
                     * 通过field的set方法set那个对象
                     *
                     */
                    Element elementSecondeChild = itSecond.next();
                    //setter注入,就是给属性值赋值
                    if (elementSecondeChild.getName().equals("property")) { //property就是setter注入方式,本来应该是根据stter后的名称注入,但是这里是采用属性的名称注入的方式
                        object = classzz.newInstance();//实例化bean UserServiceImp
                        String refValue = elementSecondeChild.attribute("ref").getValue(); //获取依赖的类的对象
                        Object injectObject = map.get(refValue);//获取实例对象
                        String nameValue = elementSecondeChild.attribute("name").getValue(); //这里本来是要执行set+"name"的方法,但是简单做法,直接给成员变量赋值
                        Field field = classzz.getDeclaredField(nameValue);//类对象里面的值变量
                        if (field == null) {
                            throw new NoFieldException("类中没有这个属性");
                        }
                        field.setAccessible(true);
                        field.set(object, injectObject);//(obj,value)  object(对象UserServiceImp对象)的成员变量field(UserDao) = injectObject(map中已经实例化的对象UserDao)
                    } else if(elementSecondeChild.getName().equals("constructor-arg")){
                        //构造方法注入
                        //获取构造方法里面的成员变量(属性)
//                        Attribute name = elementSecondeChild.attribute("name");
//                        Constructor constructor = classzz.getConstructor(name.getClass());
//                        String refValue = elementSecondeChild.attribute("ref").getValue(); //获取依赖的类的对象
//                        Object injectObject = map.get(refValue);//获取实例对象
//                        object = constructor.newInstance(injectObject);
                        String refValue = elementSecondeChild.attribute("ref").getValue();
                        Object injectObject = map.get(refValue);
                        Class injectObjectClass = injectObject.getClass();
                        Constructor constructor = classzz.getConstructor(injectObjectClass.getInterfaces()[0]); //根据接口注入 UserDao, 获取类之后还要获取接口
                        object = constructor.newInstance(injectObject);
                    }
                    else{
                        throw new NoSuchElementException("没有这个属性");
                    }
                }
                if (object == null) { //byName优先,byType后面
                    if (flag) {
                        if (default_autowire.getValue().equals("byType")) { //class类型
                            //判断是否有依赖,就是判断有没有属性
                            Field[] declaredFields = classzz.getDeclaredFields();
                            for (Field declaredField : declaredFields) {
                                Class<?> injectObjectClass = declaredField.getType();
                                /**
                                 * 由于是bytype 所以需要便利map当中的所有对象
                                 * 判断对象的类型是不是和这个injectObjectClass相同
                                 */
                                int count = 0;
                                Object injectObject = null;
                                for (String key : map.keySet()) {
                                    Class temp = map.get(key).getClass().getInterfaces()[0];
                                    if (temp.getName().equals(injectObjectClass.getName())) {
                                        injectObject = map.get(key);
                                        count++;
                                    }
                                }
                                if (count > 1) {
                                    throw new TooManyObjectException("需要一个对象,但是找到了多个对象");
                                } else {
                                    /**
                                     * 必须要有无参构造函数或者默认构造函数才可以运行
                                     */
                                    object = classzz.newInstance(); //对象
                                    declaredField.setAccessible(true);
                                    declaredField.set(object, injectObject);
                                }
                            }

                        }
                    }
                }
                //没有子标签
                if (object == null) {
                    object = classzz.newInstance();
                }
                map.put(beanName, object);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(map);
    }

    public Object getBean(String beanName) {
        return map.get(beanName);
    }
}
package org.spring.util;

public class NoFieldException extends RuntimeException {
    public NoFieldException(String str){
        super(str);
    }
}
package org.spring.util;

public class TooManyObjectException extends RuntimeException {
    public TooManyObjectException(String msg){
        super(msg);
    }
}
  • dao
package com.luban.dao;

public interface UserDao {
    public void query();
}

package com.luban.dao;
public class UserDaoImp implements UserDao{
    @Override
    public void query() {
        System.out.println("UserDao1");
    }
}
package com.luban.dao;

public class UserDaoImp2 implements UserDao{
    @Override
    public void query() {
        System.out.println("UserDao2");
    }
}
  • service
package com.luban.service;

import com.luban.dao.UserDao;

//代理
public interface UserService {
    public void find();
}
//代理实现
public class UserServiceImp implements UserService {
    UserDao propertydao;

    @Override
    public void find() {
        System.out.println("service");
        propertydao.query();
    }

    public void setDao(UserDao dao) {   //装饰者模式
        this.propertydao = dao;
    }
}
package com.luban.test;

import com.luban.dao.UserDao;
import com.luban.service.UserService;
import com.luban.service.UserServiceImp;
import org.spring.util.BeanFactory;

public class Test {
    public static void main(String[] args) {
        BeanFactory beanFactory = new BeanFactory("spring.xml");
        UserService service = (UserService) beanFactory.getBean("service");
        service.find();

    }
}

模拟AOP

申明一个Bean,有三种办法:

  • XML配置()
  • @Component(注解)
  • Java Config(@Bean,或者扫描)

在这里插入图片描述

package com.luban.anno;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com")
public class SpringConfig {
}
package com.luban.dao;

import org.springframework.beans.factory.FactoryBean;
import org.springframework.stereotype.Component;

/**
 *
 *  如果你的类实现了FactoryBean
 *  那么Spring容器当中存在两个对象
 *  一个叫是getObject()返回的对象
 *  还有一个是当前对象(daoFactoryBean)
 *
 *  getObject得到的对象存的是当前类指定的名字
 *  当前对象是“&”+但前的名字
 *
 */

@Component("daoFactoryBean")
public class DaoFactoryBean implements FactoryBean {
    public void func(){
        System.out.println("DaoFactoryBean");
    }

    @Override
    public Object getObject() throws Exception {
        return new TestFactoryBean();
    }

    @Override
    public Class<?> getObjectType() {
        return TestFactoryBean.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}
@Component("testFactoryBean")
public class TestFactoryBean {
    public void func(){
        System.out.println("testFactoryBean");
    }
}

public class Test {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
        TestFactoryBean daoFacrotyBean = (TestFactoryBean) annotationConfigApplicationContext.getBean("daoFactoryBean");
        daoFacrotyBean.func();
    }
}

在这里插入图片描述
根据结果可以知道取得Bean的名字是"daoFactoryBean",给的类型却是TestFactoryBean.

public class Test {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
        DaoFactoryBean daoFacrotyBean = (DaoFactoryBean) annotationConfigApplicationContext.getBean("&daoFactoryBean");
        daoFacrotyBean.func();
    }
}

在这里插入图片描述

FactoryBean: 当引用第三方的类时,第三方类中有很多其他的属性,我们就使用FactoryBean(简化配置)(也是一个Bean, 造Bean )
BeanFactory:Bean工厂,管理Bean

初始化Spring的环境有几种办法:
xml ClassPathXmlApplicationContext 类的扫描 单独bean的注册(声明和注册)
annotation
javaconfig AnnotationConfigApplication 类的扫描 类的定义(没有类的注册)

注册Bean(@Bean, <bean>, register(需要refresh),@Autowired, @Component )

所谓的初始化spring环境—>把我们交给spring管理的类实例化

public class Test {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext =
                new AnnotationConfigApplicationContext();
        annotationConfigApplicationContext.refresh(SpringConfig.class);
        annotationConfigApplicationContext.register(Userdao.class);
        annotationConfigApplicationContext.refresh();
    }
}

自定义扫描注解

在这里插入图片描述

@Retention(RetentionPolicy.RUNTIME)  //一定要加上,否则运行时会忽略
public @interface Luban {
    public String  value();
}

@Luban("service")
public class UserServiceImp implements UserService {
}
public class AnnotationConfigApplicationContext {
    //最终得到类(Object)
    public void scan(String basePackage){
        String rootPath = this.getClass().getResource("/").getPath();
        String basePackagePath = basePackage.replaceAll("\\.","\\\\");
        File file = new File(rootPath +"//" + basePackagePath);

        String names[] = file.list();
        for (String name : names) {
            name = name.replaceAll(".class","");
            try {
                Class clazz = Class.forName(basePackage + "." + name);
                if(clazz.isAnnotationPresent(Luban.class)){
                    Luban luban = (Luban) clazz.getAnnotation(Luban.class);
                    System.out.println(luban.value());
                    System.out.println(clazz.newInstance());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
public class Test {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext =
                new AnnotationConfigApplicationContext();
        annotationConfigApplicationContext.scan("com.luban.service");

    }
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值