tiny-Spring【1】

Spring框架的两大特性:IOC、AOPjava

 

1,IOC特性

  IOC:IOC,另一种说法叫DI(Dependency Injection),即依赖注入。它并非一种技术实现,而是一种设计思想spring

  在任何一个有实际开发意义的程序项目中,咱们会使用不少类来描述它们特有的功能,而且经过类与类之间的相互协做来完成特定的业务逻辑。这个时候,每一个类都须要负责管理与本身有交互的类的引用和依赖,代码将会变的异常难以维护和极度的高耦合。而IOC的出现正是用来解决这个问题,咱们经过IOC将这些相互依赖对象的建立、协调工做交给Spring容器去处理,每一个对象只须要关注其自身的业务逻辑关系就能够了。在这样的角度上来看,得到依赖的对象的方式,进行了反转,变成了由Spring容器控制对象如何获取外部资源(包括其余对象和文件资料等等)

编程

大白话就是:安全

咱们在完成一些生产生活劳做【业务逻辑】的时候,须要使用到其余的工具【其余实例化对象-如斧头、镰刀、马车等】;在以前咱们都是本身去实例化【自给自足-手动new一个个工具】,效率很低。

到了现代社会【Spring相似框架出现后】,咱们自用关注咱们的工做和生活就好了,其余的那些工具交给这个现代社会【Spring来进行对象的实例化】去完成。

之前是,咱们主动去new一个工具,如今变成被动的接收工具。你如今不可能本身去造一辆地铁了吧!直接我要用的话,直接去用就完事了。框架

2,AOP特性

  AOP:面向切面编程,每每被定义为促使软件系统实现关注点的分离的技术ide

  系统是由许多不一样的组件所组成的,每个组件各负责一块特定功能。除了实现自身核心功能以外,这些组件还常常承担着额外的职责。例如日志、事务管理和安全这样的核心服务常常融入到自身具备核心业务逻辑的组件中去。这些系统服务常常被称为横切关注点,由于它们会跨越系统的多个组件。工具

通知: 通知定义了切面是什么以及什么时候使用的概念。Spring 切面能够应用5种类型的通知:测试

  •   前置通知(Before):在目标方法被调用以前调用通知功能。
  •   后置通知(After):在目标方法完成以后调用通知,此时不会关心方法的输出是什么。
  •   返回通知(After-returning):在目标方法成功执行以后调用通知。
  •   异常通知(After-throwing):在目标方法抛出异常后调用通知。
  •   环绕通知(Around):通知包裹了被通知的方法,在被通知的方法调用以前和调用以后执行自定义的行为。

链接点:是在应用执行过程当中可以插入切面的一个点。this

切点: 切点定义了切面在何处要织入的一个或者多个链接点。
切面:是通知和切点的结合。通知和切点共同定义了切面的所有内容。
引入:引入容许咱们向现有类添加新方法或属性。
织入:是把切面应用到目标对象,并建立新的代理对象的过程。切面在指定的链接点被织入到目标对象中。在目标对象的生命周期中有多个点能够进行织入:
编译期: 在目标类编译时,切面被织入。这种方式须要特殊的编译器。AspectJ的织入编译器就是以这种方式织入切面的。
类加载期:切面在目标加载到JVM时被织入。这种方式须要特殊的类加载器(class loader)它能够在目标类被引入应用以前加强该目标类的字节码。
运行期: 切面在应用运行到某个时刻时被织入。通常状况下,在织入切面时,AOP容器会为目标对象动态地建立一个代理对象。SpringAOP就是以这种方式织入切面的。

spa

3,tiny-Spring

参考-黄亿华的tiny-Spring

3.1 Step1

BeanFactory.java工厂模式接口
package com.cnblogs.Factory;

public interface BeanFactory {
    /**
     * 工厂模式中的接口,用于产生实体类
     * @param name
     * @return
     * @throws Exception
     */
    Object getBean(String name) throws Exception;
}

 

AbstractBeanFactory.java注册表类型【登记已经有的实例】
package com.cnblogs.Factory;

import com.cnblogs.bean.BeanDefinition;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class AbstractBeanFactory implements BeanFactory {
    private Map<String, BeanDefinition> beanDefinitionMap=new ConcurrentHashMap<String, BeanDefinition>();//线程安全-散列表
    private final List<String> beanDefinitionNames=new ArrayList<String>();//实体对象名称

    @Override
    public Object getBean(String name) throws Exception {
        BeanDefinition beanDefinition=beanDefinitionMap.get(name);
        if(beanDefinition==null){
            throw new IllegalArgumentException("No bean named"+name+" is defined");
        }
        Object bean=beanDefinition.getBean(name);
        return bean;
    }

    //本质上就是进行名称和对象的映射到散列表上
    public void registerBeanDefinition(String name,BeanDefinition beanDefinition) throws Exception{
        beanDefinitionMap.put(name,beanDefinition);
        beanDefinitionNames.add(name);
    }
}

 

BeanDefinition.java 传入实例【相似包装盒的做用-里面的东西能够千差万别】
package com.cnblogs.bean;


/**
 * bean的内容及元数据,保存在BeanFactory中,包装bean的实体
 */

public class BeanDefinition {
    private Object bean;
    private Class<?> beanClass;
    private String  beanClassName;
    public BeanDefinition(){}
    public BeanDefinition(Object object){
        this.bean=object;
    }

    public void setBeanClassName(String beanClassName) throws ClassNotFoundException {
        this.beanClassName=beanClassName;
        try{
            this.beanClass=Class.forName(beanClassName);
        }catch(ClassNotFoundException e){
            e.printStackTrace();
        }
    }

}

 

Client.java测试类
import com.cnblogs.Factory.AbstractBeanFactory;
import com.cnblogs.Factory.BeanFactory;
import com.cnblogs.bean.BeanDefinition;

class HelloWorldServiceImpl {

    public void helloWorld2() {
        System.out.println("hello");
    }
}

public class Client {
    public static void Step1() throws Exception{
        BeanFactory beanFactory=new AbstractBeanFactory();
        BeanDefinition beanDefinition=new BeanDefinition(new HelloWorldServiceImpl());

        ((AbstractBeanFactory)beanFactory).registerBeanDefinition("helloworld",beanDefinition);

        HelloWorldServiceImpl h=(HelloWorldServiceImpl) beanFactory.getBean("helloworld");
        h.helloWorld2();
    }


    public static void main(String[] args) throws Exception {
        Client.Step1();
    }
}
View Code
 

3.2 Step2【利用反射机制传入String 类名-实例化对象】

 

    public static void Step2() throws Exception{
        BeanFactory beanFactory=new AbstractBeanFactory();//无参构造,不传入实例
        BeanDefinition beanDefinition=new BeanDefinition();
        beanDefinition.setBeanClassName("com.spring.step1.test.HelloWorldServiceImpl");

        ((AbstractBeanFactory) beanFactory).registerBeanDefinition("helloworld",beanDefinition);

        HelloWorldServiceImpl h=(HelloWorldServiceImpl) beanFactory.getBean("helloworld");
        h.helloWorld2();
    }

AbstractBeanFactory/getBean()方法

    @Override
    public Object getBean(String name) throws Exception {
        BeanDefinition beanDefinition=beanDefinitionMap.get(name);
        if(beanDefinition==null){
            throw new IllegalArgumentException("No bean named "+name+" is defined");
        }
        Object bean=beanDefinition.getBean();
        if (bean==null) {
            Constructor constructor=beanDefinition.getBeanClass().getDeclaredConstructor();
            constructor.setAccessible(true);//设置权限
            bean=constructor.newInstance();
            beanDefinition.setBean(bean);
        }
        return bean;
    }

 

3.3 step3【注入参数】

以前的实体类HelloWorldServiceImpl中有属性后

private String text;
private int a;

HelloWorldServiceImpl实体类
class HelloWorldServiceImpl {
    private String text;
    private int a;

    public HelloWorldServiceImpl(){}

    public void helloWorld2(){
        System.out.println("hello");
    }

    public void helloWorld3() {
        System.out.println(text + a + " ss");
    }
}
PropertyValue封装类
package com.spring.step1.bean;

/**
 * 用于bean的属性注入
 * 和BeanDefinition一个效果,将实体进行封装到一个动态类中
 */
public class PropertyValue {
    private final String name;
    private final Object value;  //    省略get/set  后文对简单的get/set方法将直接省略 再也不说明

    public PropertyValue(String name, Object value) {
        this.name = name;
        this.value = value;
    }

    public String getName() {
        return name;
    }

    public Object getValue() {
        return value;
    }
}
PropertyValues封装类
package com.spring.step1.bean;

import java.util.ArrayList;
import java.util.List;

/**
 * 包装一个对象全部的PropertyValue。<br/>
 * 为何封装而不是直接用List?由于能够封装一些操做。
 * 单纯的一个ArrayList对象,其中封装了一些实体对象
 */
public class PropertyValues {
    private final List<PropertyValue> propertyValueList = new ArrayList<PropertyValue>();
    public PropertyValues(){}

    public void addPropertyValue(PropertyValue pv){
        //TODO:这里能够对于重复propertyName进行判断,直接用list无法作到
        //    System.out.println(pv.getName()+pv.getValue());
        this.propertyValueList.add(pv);
    }
    public List<PropertyValue> getPropertyValues() {
        return this.propertyValueList;
    }
}

在BeanDefinition里加入【private PropertyValues propertyValues;】setter和getter默认

AbstractBeanFactory类中的getBean也要进行相关修改
    @Override
    public Object getBean(String name) throws Exception {
        BeanDefinition beanDefinition=beanDefinitionMap.get(name);
        if(beanDefinition==null){
            throw new IllegalArgumentException("No bean named "+name+" is defined");
        }

        Object bean=beanDefinition.getBean();
        if (bean==null) {
            Constructor constructor=beanDefinition.getBeanClass().getDeclaredConstructor();
            constructor.setAccessible(true);//设置权限
            bean=constructor.newInstance();
            constructor.setAccessible(false);//设置权限
            beanDefinition.setBean(bean);
        }
        creatBean(bean, beanDefinition);
        return bean;
    }

    public void creatBean(Object bean, BeanDefinition beanDefinition) throws Exception{
        if(beanDefinition.getPropertyValues() != null)
            creatBeanWithProperty(bean, beanDefinition);
    }

    public void creatBeanWithProperty(Object bean, BeanDefinition beanDefinition) throws Exception{
        int size =beanDefinition.getPropertyValues().getPropertyValues().size();//List长度
        List<PropertyValue> list = beanDefinition.getPropertyValues().getPropertyValues();//由外及内
        for (int i = 0; i <size ; i++) {
            if(list.get(i).getValue() instanceof BeanReference) {
                String beanName = ((BeanReference) list.get(i).getValue()).getName();
                Object referenceBean = getBean(beanName);
                String ms = "set" + Character.toUpperCase(list.get(i).getName().charAt(0)) + list.get(i).getName().substring(1);
                Method m = bean.getClass().getDeclaredMethod(ms, referenceBean.getClass());//反射机制的数据配置-初始化处理
                m.invoke(bean, referenceBean);
            }else {//手动进行赋值
                String fieldName = list.get(i).getName();
                Object value = list.get(i).getValue();
                Field field = bean.getClass().getDeclaredField(fieldName); // getDeclaredField是得到全部的字段(不只仅是public)
                field.setAccessible(true); // 这一步必须有
                field.set(bean, value);
                field.setAccessible(false); // 这一步必须有
            }
        }
    }

测试类step3

    public static void Step3() throws Exception {
        // 1.初始化beanfactory
        BeanFactory beanFactory = new AbstractBeanFactory();
        // 2.bean定义
        BeanDefinition beanDefinition = new BeanDefinition();
        beanDefinition.setBeanClassName("com.spring.step1.test.HelloWorldServiceImpl");
        // 3.设置属性
        PropertyValues propertyValues = new PropertyValues();
        propertyValues.addPropertyValue(new PropertyValue("text","Hello World!"));
        propertyValues.addPropertyValue(new PropertyValue("a",new Integer(15)));
        beanDefinition.setPropertyValues(propertyValues);
        // 4.注册bean
        ((AbstractBeanFactory)beanFactory).registerBeanDefinition("helloworld", beanDefinition);

        HelloWorldServiceImpl h = (HelloWorldServiceImpl) beanFactory.getBean("helloworld");
        h.helloWorld3();
    }

3.4 step4【加入引用变量】

引用实体类

package com.spring.step1.test;

public class OutputService {
    public static void output(String text){
        System.out.println(text);
    }
}

加入引用变量

 

 

 

 

 

参考连接:

http://www.javashuo.com/article/p-bsstwobq-dn.html【这个讲的很清楚啊,举得例子和现实很贴切】

https://blog.csdn.net/dlf123321/article/details/39994071

相关文章
相关标签/搜索