1.自研框架IOC实现前奏【从项目开发到框架开发的转换】

目录

 

 

1.尝试引入简单工厂模式

2.尝试引入工厂方法模式:

3.尝试引入抽象工厂模式:

4.反射:

1.获取构造方法并使用【公有,私有】

2.获取类的成员变量并使用:

1.构建反射目标类 ReflectTarget  【在原先的基础上添加了一些成员变量】

2. 构建获取成员变量的类:

          3.获取类的成员方法并使用:

5.注解:

1.注解的功能:

2.注解分类

         3.自定义注解的实现:

 


 

1.尝试引入简单工厂模式

 

简单工厂并不是一种设计模式,更多算是一种编程习惯,

定义:定义一个工厂类,根据传入的参数的值不同返回不同的实例。

特点:被创建的实例具有共同的父类或接口。

 

1.共同接口 Mouse :

 


public interface Mouse {

      void sayHi();
}

2. 两个实现类:

DellMouse 类:

public class DellMouse implements Mouse {
    @Override
    public void sayHi() {
        System.out.println("我是戴尔鼠标");
    }
}

 

HpMouse类:


public class HpMouse implements Mouse {
    @Override
    public void sayHi() {
        System.out.println("我是惠普鼠标");
    }
}

 

3. 简单工厂类:


public class MouseFactory {

       public static Mouse createMouse(int type){
             switch (type){
                 case 0 :return  new DellMouse();
                 case 1: return  new HpMouse();
                 default: return new DellMouse();
             }
       }

    public static void main(String[] args) {
          Mouse mouse=MouseFactory.createMouse(1);
          mouse.sayHi();
    }
}

 

使用场景: 1. 需要创建的对象较少。 2. 客户不关心对象创建的具体细节。

 

 

 

 

 

2.尝试引入工厂方法模式:

 

定义一个用于创建对象的接口,让子类决定实例化哪一个类。

 

1. 定义一个 MouseFactory 接口:


public interface MouseFactory {
      Mouse createMouse();
}

 

2. 每一个特定的鼠标类对应一个创建工厂:

  DellMouseFactory 工厂类

public class DellMouseFactory implements  MouseFactory {
    @Override
    public Mouse createMouse() {
        return new DellMouse();
    }
}

HpMouseFactory 工厂类


public class HpMouseFactory implements MouseFactory {
    @Override
    public Mouse createMouse() {
        return new HpMouse();
    }
}

 

3. 创建shilling:


public class FactoryMouseDemo {

    public static void main(String[] args) {
            MouseFactory mouseFactory =new  HpMouseFactory();
            Mouse mouse =mouseFactory.createMouse();
            mouse.sayHi();
    }
}

1. 工厂方法模式优点:1.符合开闭原则,

           2.单一职责原则,

          3. 对客户隐藏对象的创建具体细节。

 

 2.  当需要新增一个 联想鼠标类时:

                                 1.  对于简单工厂来说 需要修改 MouseFactory 类中的代码,违反了开闭原则。

                                  2. 对于工厂方法模式来说:只需要新增一个LenovoMouseFactory 类,不需要改变现有的代码

 

3.

由于没有像简单工厂模式一样使用静态的 工厂方法,工厂方法模式可以形成继承的等级结构,扩展出子工厂的子类。

比如:IBM 被 联想收购

 

联想鼠标:

public class LenovoMouse implements Mouse  {
    @Override
    public void sayHi() {
        System.out.println("我是联想鼠标");
    }
}

 

 

联想工厂:

public class LenovoMouseFactory  implements MouseFactory  {
    @Override
    public Mouse createMouse() {
        return new LenovoMouse();
    }
}

 

 

 

IBM鼠标:


public class IBMMouse implements Mouse {
    @Override
    public void sayHi() {
        System.out.println("我是联想旗下的IBM鼠标");
    }
}

 

IBM鼠标工厂:


public class IBMMouseFactory extends LenovoMouseFactory {

     @Override
      public Mouse createMouse(){
          return new IBMMouse();
      }
}

 

工厂方法模式 是简单工厂模式  进一步的抽象和扩展,在保留简单工厂封装优点的同时,让扩展变得简单,让继承变得可行,

增加了多态的体现。

但是工厂方法模式 也有 两个严重缺点:

添加新产品类时,也要添加与之对应的工厂类,系统类的个数将成对增加,在一定程度上增加了系统的复杂度。

只支持同一类产品的创建,随着业务的增长,不可能只有鼠标,还可能有键盘,电脑等等。

总结:后续不利于扩展。

 

 

 

3.尝试引入抽象工厂模式:

 

提供一个 创建一系类 相关或相互依赖对象的接口

1. 键盘 接口:


public interface Keyboard {
      void sayhello();
}

戴尔键盘:

public class DellKeyboard implements Keyboard{

    @Override
    public void sayhello() {
        System.out.println("我是戴尔键盘");
    }
}

 

惠普键盘:

public class HpKeyboard implements Keyboard {
    @Override
    public void sayhello() {
        System.out.println("我是惠普键盘");
    }
}

 

 

2. 电脑工厂 接口:


public interface ComputerFactory {
     Mouse createMouse();
     Keyboard createKeyboard();
}

 

 惠普的:

 

public class HpComputerFactory implements ComputerFactory {
    @Override
    public Mouse createMouse() {
        return new HpMouse();
    }

    @Override
    public Keyboard createKeyboard() {
        return new HpKeyboard();
    }
}

 

戴尔的:

public class DellComputerFactory implements ComputerFactory {
    @Override
    public Mouse createMouse() {
        return new DellMouse();
    }

    @Override
    public Keyboard createKeyboard() {
        return new DellKeyboard();
    }
}

 

 

3. 实现:


public class AbstractFactoryDemo {

    public static void main(String[] args) {
        ComputerFactory cf =new HpComputerFactory();
        Mouse mouse=cf.createMouse();
        Keyboard keyboard=cf.createKeyboard();
        mouse.sayHi();
        keyboard.sayhello();
    }

}

 

抽象工厂模式 是工厂方法模式 的升级版本,解决了工厂模式只能 生产一种产品的弊端。

 

抽象工厂模式的缺点:

添加新产品时依旧违背开闭原则,比如惠普新增耳机,依旧要在ComputerFactory 接口进行修改,并且也要在 HpComputerFactory 类中修改。

 

 

 

4.反射:

 

反射的主要用法

 

 

1.获取构造方法并使用【公有,私有】

 

/*
 * 通过Class对象可以获取某个类中的:构造方法;
 *
 * 获取构造方法:
 *         1).批量的方法:
 *             public Constructor[] getConstructors():所有"公有的"构造方法
              public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有)
 *         2).获取单个的方法,并调用:
 *             public Constructor getConstructor(Class... parameterTypes):获取单个的"公有的"构造方法:
 *             public Constructor getDeclaredConstructor(Class... parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有;
 *
 *             调用构造方法:
 *             Constructor-->newInstance(Object... initargs)
 */

 

 

1.构建反射目标类 ReflectTarget: 共有6中构造方法


public class ReflectTarget {
    //---------构造函数-----------
    //(默认的带参数构造函数)
    ReflectTarget(String str) {
        System.out.println("(默认)的构造方法 s = " + str);
    }

    //无参构造函数
    public ReflectTarget() {
        System.out.println("调用了公有的无参构造方法 。。。");
    }

    //有一个参数的构造函数
    public ReflectTarget(char name) {
        System.out.println("调用了带有一个参数的构造方法,参数值为 " + name);
    }

    //有多个参数的构造函数
    public ReflectTarget(String name, int index) {
        System.out.println("调用了带有多个参数的构造方法,参数值为【目标名】: " + name + " 【序号】" + index);
    }
    //受保护的构造函数
    protected ReflectTarget(boolean n){
        System.out.println("受保护的构造方法 n :" + n);
    }
    //私有的构造函数
    private ReflectTarget(int index){
        System.out.println("私有的构造方法 序号:" + index);
    }



  
}

 

2. 获取构造方法:

public class ConstructorCollector {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Class clazz = Class.forName("demo.reflect.ReflectTarget");
        //1.获取所有的公有构造方法
        System.out.println("**********************所有公有构造方法*********************************");
        Constructor[] conArray = clazz.getConstructors();
        for(Constructor c : conArray){
            System.out.println(c);
        }

        //2.获取所有构造方法
        System.out.println("************所有的构造方法(包括:私有、受保护、默认、公有)***************");
        conArray = clazz.getDeclaredConstructors();
        for(Constructor c : conArray){
            System.out.println(c);
        }
        //3.获取单个带参数的公有方法
        System.out.println("*****************获取公有、有两个参数的构造方法*******************************");
        Constructor con = clazz.getConstructor(String.class, int.class);
        System.out.println("con = " + con);
        //4.获取单个私有的构造方法
        System.out.println("******************获取私有构造方法*******************************");
        con = clazz.getDeclaredConstructor(int.class);
        System.out.println("private con = " + con);
        System.out.println("******************调用私有构造方法创建实例*******************************");

    }
}

3.创建实例:

 

调用私有的构造:

    //4.获取单个私有的构造方法
        System.out.println("******************获取私有构造方法****************************");
        Constructor con = clazz.getDeclaredConstructor(int.class);
        System.out.println("private con = " + con);
        System.out.println("******************调用私有构造方法创建实例*****************");
        //暴力访问(忽略掉访问修饰符,如果没有,则不能访问)
        con.setAccessible(true);
        ReflectTarget reflectTarget = (ReflectTarget) con.newInstance(1);

 

调用公有的构造方法:

   //5.获取单个公有的构造方法
        System.out.println("******************获取私有构造方法*******************************");
        con = clazz.getConstructor(String.class, int.class);
        System.out.println("public con = " + con);
        System.out.println("******************调用公有构造方法创建实例*******************************");

        ReflectTarget rt = (ReflectTarget) con.newInstance("公有的拉拉",1);

 

2.获取类的成员变量并使用:

 

 

/*
 * 获取成员变量并调用:
 *
 * 1.批量的
 *      1).Field[] getFields():获取所有的"公有字段" 【包含继承的字段】

 *      2).Field[] getDeclaredFields():获取所有字段,包括:私有、受保护、默认、公有;【不包含继承的字段】

 * 2.获取单个的:
 *      1).public Field getField(String fieldName):获取某个"公有的"字段;【包含继承的字段】

 *      2).public Field getDeclaredField(String fieldName):获取某个字段(可以是私有的) 【不包含继承的字段】
 *
 *   设置字段的值:
 *      Field --> public void set(Object obj,Object value):
 *                  参数说明:
 *                  1.obj:要设置的字段所在的对象;
 *                  2.value:要为字段设置的值;
 *
 */

 

 

 

1.构建反射目标类 ReflectTarget  【在原先的基础上添加了一些成员变量】

 

public class ReflectTarget {
    //---------构造函数-----------
    //(默认的带参数构造函数)
    ReflectTarget(String str) {
        System.out.println("(默认)的构造方法 s = " + str);
    }

    //无参构造函数
    public ReflectTarget() {
        System.out.println("调用了公有的无参构造方法 。。。");
    }

    //有一个参数的构造函数
    public ReflectTarget(char name) {
        System.out.println("调用了带有一个参数的构造方法,参数值为 " + name);
    }

    //有多个参数的构造函数
    public ReflectTarget(String name, int index) {
        System.out.println("调用了带有多个参数的构造方法,参数值为【目标名】: " + name + " 【序号】" + index);
    }
    //受保护的构造函数
    protected ReflectTarget(boolean n){
        System.out.println("受保护的构造方法 n :" + n);
    }
    //私有的构造函数
    private ReflectTarget(int index){
        System.out.println("私有的构造方法 序号:" + index);
    }

    //**************字段*******************//
    public String name;
    protected int index;
    char type;
    private String targetInfo;
    @Override
    public String toString(){
        return "ReflectTarget [name=" + name + ", index=" + index + ", type=" + type
                + ", targetInfo=" + targetInfo + "]";
    }


 
}

 

2. 构建获取成员变量的类:


public class FieldCollector {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {


        //获取Class对象
        Class reflectTargetClass = Class.forName("demo.reflect.ReflectTarget");


        //1.获取所有公有的字段
        System.out.println("************获取所有公有的字段********************");
        Field[] fieldArray = reflectTargetClass.getFields();
        for (Field f : fieldArray){
            System.out.println(f);
        }


        //2.获取所有的字段
        System.out.println("************获取所有的字段(包括私有、受保护、默认的)********************");
        fieldArray = reflectTargetClass.getDeclaredFields();
        for (Field f : fieldArray){
            System.out.println(f);
        }


        //3.获取单个特定公有的field
        System.out.println("*************获取公有字段并调用***********************************");
        Field f = reflectTargetClass.getField("name");
        System.out.println("公有的field name : " + f);
         // 调用的是无参的构造函数
        ReflectTarget reflectTarget = (ReflectTarget)reflectTargetClass.getConstructor().newInstance();


        //4.给获取到的field赋值
        f.set(reflectTarget, "待反射一号");


        //5.验证对应的值name
        System.out.println("验证name : " + reflectTarget.name);


        //6.获取单个私有的Field
        System.out.println("**************获取私有字段targetInfo并调用********************************");
        f = reflectTargetClass.getDeclaredField("targetInfo");
        System.out.println(f);
        f.setAccessible(true);
        f.set(reflectTarget, "13810592345");
        System.out.println("验证信息" + reflectTarget);
    }
}

 

 

3.获取类的成员方法并使用:

1. 构建目标类:ReflectTarget

 

 

package demo.reflect;

public class ReflectTarget extends ReflectTargetOrigin{
    //---------构造函数-----------
    //(默认的带参数构造函数)
    ReflectTarget(String str) {
        System.out.println("(默认)的构造方法 s = " + str);
    }

    //无参构造函数
    public ReflectTarget() {
        System.out.println("调用了公有的无参构造方法 。。。");
    }

    //有一个参数的构造函数
    public ReflectTarget(char name) {
        System.out.println("调用了带有一个参数的构造方法,参数值为 " + name);
    }

    //有多个参数的构造函数
    public ReflectTarget(String name, int index) {
        System.out.println("调用了带有多个参数的构造方法,参数值为【目标名】: " + name + " 【序号】" + index);
    }
    //受保护的构造函数
    protected ReflectTarget(boolean n){
        System.out.println("受保护的构造方法 n :" + n);
    }
    //私有的构造函数
    private ReflectTarget(int index){
        System.out.println("私有的构造方法 序号:" + index);
    }

    //**************字段*******************//
    public String name;
    protected int index;
    char type;
    private String targetInfo;
    @Override
    public String toString(){
        return "ReflectTarget [name=" + name + ", index=" + index + ", type=" + type
                + ", targetInfo=" + targetInfo + "]";
    }
    //***************成员方法***************//
    public void show1(String s){
        System.out.println("调用了公有的,String参数的show1(): s = " + s);
    }
    protected void show2(){
        System.out.println("调用了受保护的,无参的show2()");
    }
    void show3(){
        System.out.println("调用了默认的,无参的show3()");
    }
    private String show4(int index){
        System.out.println("调用了私有的,并且有返回值的,int参数的show4(): index = " + index);
        return "show4result";
    }

}

 

2.构建获取成员方法的类:

MethodCollect


public class MethodCollect {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {

           // 1. 获取 Class 对象
           Class reflectTargetClass =Class.forName("demo.reflect.ReflectTarget");

           //2. 获取所有公有方法
           System.out.println("*****************获取所有public方法,包括父类 和Object ********************");
           Method[] methodArray = reflectTargetClass.getMethods();
           for (Method m :methodArray){
               System.out.println(m);
           }

            //3. 获取该类的所有方法
            System.out.println("*****************获取该类所有方法,包括私有 ********************");
            methodArray = reflectTargetClass.getDeclaredMethods();
            for (Method m :methodArray){
                System.out.println(m);
            }

            //4.获取公有的show1方法
            System.out.println("*****************获取公有的show1方法 ********************");
            Method m =reflectTargetClass.getMethod("show1",String.class);
            System.out.println(m);


            //5. 调用show1 并执行
            //获取实例
            ReflectTarget reflectTarget=(ReflectTarget)reflectTargetClass.getConstructor().newInstance();
            m.invoke(reflectTarget,"待反射方法一号");


            // 6. 获取一个私有的成员方法
           System.out.println("*****************获取私有的show4方法 ********************");
           m=reflectTargetClass.getDeclaredMethod("show4",int.class);
           System.out.println(m);
           m.setAccessible(true);
           // invoke的 返回类型是Object,需要强转
           String result=String.valueOf(m.invoke(reflectTarget,20));
           System.out.println("返回值:"+result);
    }
}

 

即使是反射也需要获取 类名 和类所在的包名

1.可以用xml来保存类相关的信息以供反射调用

2.也可以用注解:

 

5.注解:

提供一种为程序元素设置元数据的方法

 

 

1.注解的功能:

 

 

2.注解分类

 

元注解:

 

 

 

 

 

3.自定义注解的实现:

自动继承 java.lang.annotation.Annotation

不能继承其他的注解,也不能实现其他的接口类

格式: 访问修饰符只能是 public 或 缺省 【缺省 只能在同一个package内使用】,一般都是定义成public

  属性名就是字段名,只不过是以方法的形式定义的,返回值是字段的类型

比如: 姓名这个字段

定义:  public String name() ; 【public String name() default "学生";】 默认值有没有都可以。

目的:用上自定义注解,并用上注解信息

想要通过反射来获得注解信息@Retention 必须是 (RetentionPolicy.RUNTIME)

1.  定义两个注解 :

 CourseInfoAnnotation

//作用在类上和方法上
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface CourseInfoAnnotation {
    //课程名称
    public String courseName();
    //课程标签
    public  String courseTag();
    //课程简介
    public String courseProfile();
    //课程序号
    public int courseIndex() default 303;
}

PersonInfoAnnotation

 

//作用在类的成员变量上
@Target(ElementType.FIELD)
//后续要在反射中获取注解相关的信息,即需要在程序运行时获取
@Retention(RetentionPolicy.RUNTIME)
public @interface PersonInfoAnnotation {

      //姓名
      public String name() default "学生";
      //年纪
      public int age() default  19;
      //性别
      public String  gender() default "男";
      //开发语言
      public String[] language();
}

 

 

2.创建一个类:ImoocCourse

在类上 使用了 @CourseInfoAnnotation 注解,并且将其属性都赋值

 


@CourseInfoAnnotation(courseName = "剑指java面试", courseTag = "面试",
        courseProfile = "不仅讲解Java相关的核心知识,还涉及网络、数据库、缓存框架等核心知识,"
                + "帮助大家构建海陆空一体化的面试护城河。"
                + "全面提升大家的内功。"
)
public class ImoocCourse {
    @PersonInfoAnnotation(name = "翔仔", language = {"Java","C++","Go","Python","PHP","JS"})
    private String author;
    @CourseInfoAnnotation(courseName = "校园商铺",
            courseTag = "实战",
            courseProfile = "手把手教会从前端到后端开发多店铺商铺管理系统,"
                    + "可以用在毕设创业中,学习完会对SSM以及Springboot有一个"
                    + "全面的了解",
            courseIndex = 144)
    public void getCourseInfo() {

    }
}

 

3.创建解析注解类:

A.isAnnotationPresent(B.class);意思就是:注释B是否在此A上。如果在则返回true;不在则返回false。


public class AnnotationParser {
    //解析类的注解
    public static  void  parseTypeAnnotation() throws ClassNotFoundException {
        Class clazz = Class.forName("demo.annotation.ImoocCourse");
        //这里获取的是class对象的注解,而不是其里面的方法和成员变量的注解,
        // 比如是获得ImoocCourse 类上的注解
        Annotation[] annotations = clazz.getAnnotations();
        for(Annotation annotation : annotations){
            CourseInfoAnnotation courseInfoAnnotation =  (CourseInfoAnnotation) annotation;
            System.out.println("课程名:" + courseInfoAnnotation.courseName() + "\n" +
                    "课程标签:" + courseInfoAnnotation.courseTag() + "\n" +
                    "课程简介:" + courseInfoAnnotation.courseProfile() + "\n" +
                    "课程序号:" + courseInfoAnnotation.courseIndex() );
        }
    }
    //解析成员变量上的标签
    public static void parseFieldAnnotation() throws ClassNotFoundException {
        Class clazz = Class.forName("demo.annotation.ImoocCourse");
        Field[] fields = clazz.getDeclaredFields();
        for(Field f : fields){
            //判断成员变量中是否有指定注解类型的注解
            boolean hasAnnotation = f.isAnnotationPresent(PersonInfoAnnotation.class);
            if(hasAnnotation){
                PersonInfoAnnotation personInfoAnnotation = f.getAnnotation(PersonInfoAnnotation.class);
                System.out.println("名字:" + personInfoAnnotation.name() + "\n" +
                        "年龄:" + personInfoAnnotation.age() + "\n" +
                        "性别:" + personInfoAnnotation.gender() + "\n");
                for(String language : personInfoAnnotation.language()){
                    System.out.println("开发语言:" + language);
                }

            }
        }
    }
    //解析方法注解
    public static void parseMethodAnnotation() throws ClassNotFoundException{
        Class clazz = Class.forName("demo.annotation.ImoocCourse");
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
            /*
             * 判断方法中是否有指定注解类型的注解
             */
            boolean hasAnnotation = method.isAnnotationPresent(CourseInfoAnnotation.class);
            if(hasAnnotation){
                CourseInfoAnnotation courseInfoAnnotation = method.getAnnotation(CourseInfoAnnotation.class);
                System.out.println("课程名:" + courseInfoAnnotation.courseName() + "\n" +
                        "课程标签:" + courseInfoAnnotation.courseTag() + "\n" +
                        "课程简介:" + courseInfoAnnotation.courseProfile() + "\n"+
                        "课程序号:" + courseInfoAnnotation .courseIndex() + "\n");
            }
        }
    }


    public static void main(String[] args) throws ClassNotFoundException {
        parseTypeAnnotation();
       // parseFieldAnnotation();
        //parseMethodAnnotation();
    }
}

 

执行结果:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值