【Java架构师入门到精通提升】自定义spring

1.1   描述

在企业级开发中,spring框架应用非常广。为了让已经学习过spring框架同学,可以更深入的理解和应用spring,本文将通过自定义spring,更佳系统的阐述spring核心:IoC、AOP。
       IoC(Inversion of Control)控制反转:将对象的创建权交与spring框架,及将创建权反转给spring框架。IoC主要解决计算机程序的耦合问题。
       AOP(Aspect Oriented Programming)面向切面编程:通过运行期动态代理实现程序功能的统一维护的一种技术。

1.2   分析

l  如果要实现自定义spring,可以将器拆分成多个功能实现。
l  阶段一:编写配置文件,服务器tomcat启动时,加载配置文件
l  阶段二:使用Jsoup解析xml,并封装到指定的JavaBean中
l  阶段三:编写工厂类用于创建指定bean,并完成property注入
l  阶段四:使用@Transactional进行事务管理

1.3   搭建环境

image

1.3.1   javabean

| public class User {

private Integer uid;
   private String username;
   private String password; |

1.3.2    dao

| public interface UserDao {
   /**
    * 保存
    * @param user
    */
   public void save(User user);

} |
| public class UserDaoImpl implements UserDao {

@Override
   public void save(User user) {
      //TODO 暂时只打印
      System.out.println(user);
   }

} |

1.3.3   service

| public interface UserService {
   /**
    * 注册
    * @param user
    */
   public void register(User user);
} |
| public class UserServiceImpl implements UserService {

private UserDao userDao;
   public void setUserDao(UserDao userDao) {
      this.userDao = userDao;
   }

@Override
   public void register(User user) {
      this.userDao.save(user);
   }
} |

1.4   阶段一:编写配置文件,服务器启动加载

1.4.1   xml配置文件

l  在src下添加“applicationContext.xml”,并将dao和service配置到xml文件中。想学习交流HashMap,nginx、dubbo、Spring MVC,分布式、高性能高可用、MySQL,redis、jvm、多线程、netty、kafka、的加尉xin(同英):1253431195 扩列获取java进阶资料学习,无工作经验不要加哦!
l  使用标签配置一个实现类
       class:    配置实现类的全限定名称
       id: 进行唯一命名,用于提供给程序获得
l  使用配置javabean属性的注入
       name:   配置的service的属性名
       ref:       配置其他bean对象的引用

image

| <?xml version=*"1.0"* encoding=*"UTF-8"*?>

   
    <bean id=“userDaoId” class=“cn.itcast.demo.dao.impl.UserDaoImpl”>
   
    <bean id=“userServiceId” class=“cn.itcast.demo.service.impl.UserServiceImpl”>
        <property name=“userDao” ref=“userDaoId”>
   
|

1.4.2   加载配置文件

l  tomcat启动时,加载配置文件方式总结:
       1.编写Servlet,配置servlet,并添加,在init(ServletConfig)初始化方式中加载。
       2.编写Filter,配置filter,在init(FilterConfig)初始化方法中加载
       3.编写Listener,实现接口ServletContext,配置listener,在contextInitialized(ServletContextEvent sce)方法中加载。
l  spring采用listener方案
       1.提供实现类ContextLoaderListener
       2.编写全局初始化参数contextConfigLocation,用于确定xml位置
              classpath:applicationContext.xml 加载类路径下的xml文件
        applicationContext.xml 加载WEB-INF目录的配置文件

l  xml配置

|
   
        contextConfigLocation
        classpath:applicationContext.xml
   


   
        cn.itcast.myspring.listener.ContextLoaderListener
    |

l  实现类

image

| public class ContextLoaderListener implements ServletContextListener {

@Override
    public void contextInitialized(ServletContextEvent sce) {
        // 0 获得ServletContext对象应用
        ServletContext context = sce.getServletContext();
        // 1 加载配置
        String config = context.getInitParameter(“contextConfigLocation”);
        if(config == null){ //默认配置文件位置
            config= “applicationContext.xml”;
        }

InputStream xmlIs = null;
        // 2  处理路径不同情况
        // * classpath:applicationContext.xml --> 表示 src/applicationContext.xml
        // * applicationContext.xml --> 表示 /WEB-INF/applicationContext.xml
        if (config.startsWith(“classpath:”)) { // 2.1 加载 类路径 (classpathsrc)下的xml
            xmlIs = ContextLoaderListener.class.getClassLoader().getResourceAsStream(config.substring(“classpath:”.length()));
        } else { //2.2 加载/WEB-INF/目录下的资源
            xmlIs = context.getResourceAsStream("/WEB-INF/" + config);
        }
        //2.3 配置文件必须存在,否则抛异常
        if(xmlIs == null){
            throw new RuntimeException(“资源文件[”+config+"]没有找到");
        }

//TODO 3 解析配置
        if (xmlIs != null) {
            System.out.println(xmlIs);
        }
    }
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
    }
} |

1.5   阶段二:解析xml,并封装到指定javabean中

1.提供Property类,用于封装<property name=" " ref=" ">
2.提供Bean类,用于封装<bean id=" " class=" ">
       一个 标签体中可以配置多个需要一个容器存放,没有顺序要求,且不能重复,选择Set
3.提供BeanFactory类,并在类同提供容器存放多个Bean 类,为了方便获取使用Map。想学习交流HashMap,nginx、dubbo、Spring MVC,分布式、高性能高可用、MySQL,redis、jvm、多线程、netty、kafka、的加尉xin(同英):1253431195 扩列获取java进阶资料学习,无工作经验不要加哦!

image

1.5.1    property javabean

| /**
 * 用于封装 <property name=“userDao” ref=“userDaoId”>
 */
public class Property {

//属性名称
   private String name;
   //另一个bean引用名
   private String ref;

public Property(String name, String ref) {
      super();
      this.name = name;
      this.ref = ref;
   } |

1.5.2    bean  javabean

| public class Bean {

//bean名称
   private String beanId;
   //bean的实现类
   private String beanClass;
   //取值:singleton 单例,prototype 原型(多例)【扩展】
   private String beanType;

//所有的property
   private Set propSet = new HashSet();

public Bean(String beanId, String beanClass) {
      super();
      this.beanId = beanId;
      this.beanClass = beanClass;
   } |

1.5.3    BeanFactory 工厂模式类

| public class BeanFactory {

//工厂模式
    private static BeanFactory factory = new BeanFactory();
    private BeanFactory(){
    }

/**
     * 获得工厂实例
     * @author lt
     * @return
     */
    public static BeanFactory getInstance() {
        return factory;
    } |

1.5.4    BeanFactory 提供Map 缓存

|     //缓存所有的Bean/
    //bean数据缓存集合 ,key:bean名称 ,value:bean封装对象
    private static Map<String, Bean> beanData;// = new HashMap<String, String>();
    static{
        // 从配置文件中获得相应的数据 1.properties 2.xml
        //beanData.put(“userDao”, “com.itheima.ebs.service.impl.BusinessServiceImpl”);
    }

public static void setBeanData(Map<String, Bean> beanData) {
        BeanFactory.beanData = beanData;
    } |

1.5.5    修改Listener解析xml

l  使用Jsoup解析,导入jar包

image

l  修改contextInitialized 方法

| //TODO 3 解析配置
      if (xmlIs != null) {
         //3.1解析
         Map<String, Bean> data = parserBeanXml(xmlIs);
         //3.2 将解析结果放置到工厂中
         BeanFactory.setBeanData(data);
      } |

l  解析方法parserBeanXml(InputStream)

| /**
    * 将数据解析成bean
    * @param xmlIs
    * @return
    */
   public static Map<String, Bean> parserBeanXml(InputStream xmlIs) {
      try {
         //0提供缓冲区域
         Map<String, Bean> data = new HashMap<String, Bean>();

//1解析文件,并获得Document
         Document document = Jsoup.parse(xmlIs, “UTF-8”, “”);

//2 获得所有的bean元素
         Elements allBeanElement = document.getElementsByTag(“bean”);

//3遍历
         for (Element beanElement : allBeanElement) {
            //5 将解析的结果封装到bean中
            // 5.1 bean名称
            String beanId = beanElement.attr(“id”);
            // 5.2 bean实现类
            String beanClass = beanElement.attr(“class”);

// 5.3 封装到Bean对象
            Bean bean = new Bean(beanId,beanClass);

// 6 获得所有的子元素 property
            Elements allPropertyElement = beanElement.children();
            for (Element propertyElement : allPropertyElement) {
                String propName = propertyElement.attr(“name”);
                String propRef = propertyElement.attr(“ref”);
                Property property = new Property(propName, propRef);

// 6.1 将属性追加到bean中
                bean.getPropSet().add(property);
            }

data.put(beanId, bean);
         }
         return data;
      } catch (Exception e) {
         throw new RuntimeException(e);
      }
   } |

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值