(一)架构师框架 - spring 框架

第一章  mybatis 框架

在了解spring 框架之前,应该先了解mybatis 框架

第二章  spring 框架使用,动态工厂,依赖注入,

今天讲解了 spring 对 bean 是怎么管理的,怎么拦截的,spring怎么对属性做依赖注入的

2.1 平时的使用

1. 定义类

2. 根据规则定义配置文件 

3. 通过工厂配置使用,可以把创建的对象监控起来,通过偷梁换柱的代理模式管理对象 

2.2 模拟简单的spring 框架处理

1. beandefind

public class BeanDefined {
    // attr
    private String beanId;
    private String classPath;
    // getter & setter
}

2. beanFactory

// 就是一系列bean对象的标签集合
public class BeanFactory {

    // 管理 bean对象
    private List<BeanDefined> beanDefinedList;

    // 提供一个获取bean的方法
    public Object getBean(String beanId) throws Exception {

        Object instance;
        for (BeanDefined beanDefined: beanDefinedList){
            if (beanDefined.getBeanId().equals(beanId)){
                String classPath = beanDefined.getClassPath();
                // 默认情况下,spring工厂通过调用当前类默认构造方法创建实例对象
                Class classFile = Class.forName(classPath);
                instance = classFile.newInstance();
                return instance;
            }
        }
        return null;   // 没找到返回空
    }
}

 3. 测试类

public class MainTest {
    public static void main(String[] args) throws Exception {
        // 1 声明注册bean
        BeanDefined beanObj = new BeanDefined();
        beanObj.setBeanId("teacher");
        beanObj.setClassPath("beans.Teacher");

        List beanList = new ArrayList();
        beanList.add(beanObj);   // spring 核心配置,添加管理一个个bean标签对象

        // 2 声明一个spring 提供 Beanfactory
        BeanFactory factory = new BeanFactory();
        factory.setBeanDefinedList(beanList);

        // 3 开发人员向 beanfactory 索要实例对象
        Teacher t = (Teacher) factory.getBean("teacher");
        System.out.println(t);
    }
}

2.3 模拟spring IOC 容器,scope 属性,分别是 singleton prototype 两种对象创建方式

2.4 spring 也允许自己创建对象,动态创建对象 - 动态工厂

不同场景下,对象的创建 不一样

2.4.1  动态工厂的使用

1. 创建自定义工厂

2.在配置文件中注册    

2.4.2 动态工厂的实现teacherFactory

框架的设计 = 设计模式 + 反射机制 +  规则

2.4.3 除了动态,spring也允许用户创建静态工厂

节省内存

public class TeacherFactory {
    public static Teacher createTecher(){  // static 节省内存消耗
        Teacher teacher = new Teacher();
        System.out.println("teacherfactory 负责创建teacher对象");
        return teacher;
    }
}

2.5  BeanPostProcessor,  监控代理使用 & 源码的实现

2.5.1 监控代理使用

在这个bean对象在被创建之后,在它的某些行为里拦截,并对所拦截的功能做一个相关的增强操作,

1 增强 - 创建接口实现

public interface BaseService {
    public String doSome();
}
public class ISomeService implements BaseService {
    public String doSome() {
        // 增强效果,doSome方法返回值都是大写
        return "hello youngpeng";
    }
}

2.  代理监控 - bean 后 增强 

public class MyBeanPostProcessor implements BeanPostProcessor {
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("bean对象初始化之前.........");
        return bean;   // 返回bean或者bean对象监控的代理对象
    }

    public Object postProcessAfterInitialization(final Object beanInstance, String beanName) throws BeansException {
        // 为当前的bean对象注册代理监控对象, 负责增强bean对象方法能力
        Class beanClass = beanInstance.getClass();
        /**
         * 这里我们做了一个监控,这里交给用户的就不是一个真实的对象了,代理对象
         */
        if (beanClass == ISomeService.class){
            Object proxy = Proxy.newProxyInstance(beanInstance.getClass().getClassLoader(), // 当前对象类属的类文件在哪里
                    beanInstance.getClass().getInterfaces(),   // 对象的那些行为要进行监控
                    new InvocationHandler() {                  // 拦截之后怎么做处理呢?
                        /**
                         * @param proxy : 代理监控对象
                         * @param method: doSome() 监控的方法
                         * @param args: dosome方法运行时接受的实参
                         * @return
                         * @throws Throwable
                         */
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            System.out.println("isomeservice dosome 方法别拦截...");
                            String result  = (String) method.invoke(beanInstance, args);
                            return result.toUpperCase();
                        }
                    }
            );
            return proxy;
        }
        return beanInstance;
    }
}

3  增强之后就开始注册了,在配置类中实现

4  测试使用

2.5.2 BeanPostProcessor 源码的实现

1  书写自己的BeanPostProcessor 接口

public interface BeanPostProcessor {
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws Exception ;

    public Object postProcessAfterInitialization(final Object beanInstance, String beanName) throws Exception;
}

2  书写自己的实现

public class MyBeanPostProcessor implements BeanPostProcessor {
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws Exception {
        System.out.println("bean对象初始化之前.........");
        return bean;   // 返回bean或者bean对象监控的代理对象
    }

    public Object postProcessAfterInitialization(final Object beanInstance, String beanName) throws Exception {
        // 为当前的bean对象注册代理监控对象, 负责增强bean对象方法能力
        Class beanClass = beanInstance.getClass();
        /**
         * 这里我们做了一个监控,这里交给用户的就不是一个真实的对象了,代理对象
         */
        if (beanClass == ISomeService.class){
            Object proxy = Proxy.newProxyInstance(beanInstance.getClass().getClassLoader(), // 当前对象类属的类文件在哪里
                    beanInstance.getClass().getInterfaces(),   // 对象的那些行为要进行监控
                    new InvocationHandler() {                  // 拦截之后怎么做处理呢?
                        /**
                         * @param proxy : 代理监控对象
                         * @param method: doSome() 监控的方法
                         * @param args: dosome方法运行时接受的实参
                         * @return
                         * @throws Throwable
                         */
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            System.out.println("isomeservice dosome 方法别拦截...");
                            String result  = (String) method.invoke(beanInstance, args);
                            return result.toUpperCase();
                        }
                    });
            return proxy;
        }
        return beanInstance;
    }
}

2.6 依赖注入 使用 & 源码分析

让spring factory 对我们的对象进行实例化操作

spring 框架通过反射机制,调用属性对应的set方法进行赋值

2.6.1  依赖注入使用

1 编写实体类

2 spring 配置文件 - 读取标签信息,通过反射调用

3 工厂去读,直接使用

 

2.6.2  DI源码实现

我们怎么让标签对象化的去显示呢?

1. 定义类

public class Teacher {
    private String teacherName;
    private String friendArray[];
    private List<String> school;
}

2. 写 beanDefind(添加一个map存放XML属性键值对)

public class BeanDefined {
    /**
     * <bean id, class, scope, factory-bean, factory-method > <bean/>
     */
    private String beanId;
    private String classPath;
    private String scope ;
    private String factoryBean = null;   // 不用判断空字符串了
    private String factoryMethod = null;
    private Map<String, String> propertyMap = new HashMap<String, String>();
}

3.  写测试类 - 注册声明bean

/**
 * 1 声明注册bean
  */
BeanDefined beanObj = new BeanDefined();
 beanObj.setBeanId("teacher");
beanObj.setScope("prototype");  // singleton  prototype
beanObj.setClassPath("beans.Teacher");
/**
 * 依赖注入相关的配置写入 map 中
 */
Map<String, String> propertyMap = beanObj.getPropertyMap();
propertyMap.put("teacherName", "李老师");
propertyMap.put("friendArray", "桂桂,花花,丽丽");
propertyMap.put("school", "北小, 北大, 中科院");

4. 依赖注入: 反射 + set 方法

/**
     * 依赖注入,赋值,类型转换
     * @param instance     反射对应配置文件的bean 实例
     * @param classFile    bean 实例 对应的类文件
     * @param propertyMap  配置文件中属性值
     */
    public void setValue(Object instance, Class classFile, Map propertyMap) throws Exception {
        // 循环遍历  propertyMap<属性名,属性值>
        Method[] methodArray  = classFile.getDeclaredMethods();  // 类文件getter setter 等方法
        Set fieldNameSet = propertyMap.keySet();  // 解析出配置文件的map中key值
        Iterator fieldIterator = fieldNameSet.iterator();
        while (fieldIterator.hasNext()){
            String fieldName = (String) fieldIterator.next();
            String value = (String) propertyMap.get(fieldName);
            Field fieldObj = classFile.getDeclaredField(fieldName);
            for (int i=0;i<methodArray.length;i++){
                Method methodObj = methodArray[i];
                String methodName = "set" + fieldName;  // 找到对应属性的set方法设置赋值
                if (methodName.equalsIgnoreCase(methodObj.getName())){
                    Class fieldType = fieldObj.getType();    // 反射拿到属性是什么类型
                    /**
                     * 进行类型的转换
                     */
                    if (fieldType == String.class){
                        methodObj.invoke(instance, value);
                    }else if(fieldType == Integer.class){
                        methodObj.invoke(instance, Integer.valueOf(value)); // 转换为int类型
                    }else if(fieldType == Boolean.class){
                        methodObj.invoke(instance, Boolean.valueOf(value));
                    }else if(fieldType == List.class){
                        List tempList = new ArrayList();
                        String dataArray[]  = value.split(",");
                        for (int j=0;j<dataArray.length;j++){
                            tempList.add(dataArray[j]);
                        }
                        methodObj.invoke(instance, tempList);
                    }else {   // 默认如果是数组类型
                        String[] dataArray = value.split(",");
                        Object data[] = new Object[1];
                        data[0] = dataArray;
                        methodObj.invoke(instance, data);
                    }
                    break;
                }
            }
        }

    }

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值