Spring初见2(基础知识)

本文介绍了Spring框架中引用类型属性的自动注入(byName和byType)以及通过注解(@Component、@Autowired)实现依赖注入的方法。涵盖了自动装配规则和使用场景,以及JDK动态代理在AOP中的应用。
摘要由CSDN通过智能技术生成

一、引用类型属性自动注入

  • 对于引用类型属性的注入,也可不在配置文件中显示的注入。可以通过为<bean/>标签 设置 autowire 属性值,为引用类型属性进行隐式自动注入(默认是不自动注入引用类型属 性)。根据自动注入判断标准的不同,可以分为两种:

    • byName:根据名称自动注入

      • 当配置文件中被调用者 bean 的 id 值与代码中调用者 bean 类的属性名相同时,可使用 byName 方式,让容器自动将被调用者 bean 注入给调用者 bean。容器是通过调用者的 bean 类的属性名与配置文件的被调用者 bean 的 id 进行比较而实现自动注入的。

    • byType: 根据类型自动注入

      • 使用 byType 方式自动注入,要求:配置文件中被调用者 bean 的 class 属性指定的类, 要与代码中调用者 bean 类的某引用类型属性类型同源。即要么相同,要么有 is-a 关系(子 类,或是实现类)。但这样的同源的被调用 bean 只能有一个。多于一个,容器就不知该匹配 哪一个了。

public class School {
​
       private String schoolName;
​
    public String getSchoolName() {
        return schoolName;
    }
​
    public void setSchoolName(String schoolName) {
        this.schoolName = schoolName;
    }
​
    @Override
    public String toString() {
        return "School{" +
                "schoolName='" + schoolName + '\'' +
                '}';
    }
}
//====================================================
public class Student {
​
       private String sname;
       private int   age;
       private School mySchool;
​
    public String getSname() {
        return sname;
    }
​
    public void setSname(String sname) {
        this.sname = sname;
    }
​
    public int getAge() {
        return age;
    }
​
    public void setAge(int age) {
        this.age = age;
    }
​
    public School getMySchool() {
        return mySchool;
    }
​
    public void setMySchool(School mySchool) {
        this.mySchool = mySchool;
    }
​
    @Override
    public String toString() {
        return "Student{" +
                "sname='" + sname + '\'' +
                ", age=" + age +
                ", mySchool=" + mySchool +
                '}';
    }
}
        <bean  id="school" class="com.pm.pack4.School">
            <property name="schoolName" value="清华大学"/>
        </bean>

         <!--
            要求Spring容器通过反射机制技术扫描当前类所有的属性。
            如果发现了引用类型属性,且在Spring容器内部存在与当前
            引用类型属性类型相匹配的对象则直接赋值(注入)
         -->
         <bean id="stu" class="com.pm.pack4.Student" autowire="byType">
             <property name="sname" value="pm"/>
             <property name="age"   value="22"/>
         </bean>
public class TestMain {
​
    @Test
    public void test4(){
        ApplicationContext spring =
                new ClassPathXmlApplicationContext("pack4/spring.xml");
        Student student=(Student) spring.getBean("stu");
        System.out.println(student.toString());
    }
}
test4结果:Student{sname='pm', age=22, mySchool=School{schoolName='清华大学'}}
        <bean  id="yourSchool" class="com.pm.pack5.School">
            <property name="schoolName" value="清华大学"/>
        </bean>
​
        <bean  id="mySchool" class="com.pm.pack5.School">
            <property name="schoolName" value="北京大学"/>
        </bean>
            
         <!--
            要求Spring容器通过反射机制技术扫描当前类所有的属性。
            如果发现了引用类型属性,且属性名称与Spring容器中
            相关对象的id是相等,则要求Spring容器将这个id关联的对象
            赋值给这个同名属性
         -->   
​
         <bean id="stu" class="com.pm.pack5.Student" autowire="byName">
             <property name="sname" value="mike"/>
             <property name="age"   value="22"/>
            <!-- <property name="mySchool"/>-->
         </bean>
public class TestMain {
​
    @Test
    public void test5(){
        ApplicationContext spring =
                new ClassPathXmlApplicationContext("pack5/spring.xml");
        Student student=(Student) spring.getBean("stu");
        System.out.println(student.toString());
    }
}
test5结果:Student{sname='mike', age=22, mySchool=School{schoolName='北京大学'}}

二、如何通过注解的方式向Spring容器索要IOC服务

  • 1、将@Compoent修饰在指定类名上,由@Compoent修饰的类,表示这个类对象需要由Spring容器提供,通过@Compoent(value = “key”) 指定当前类的实例对象在Spring容器中对应key。

    此外也有不用通过@Compoent指定key。此时当前类的实例对象在Spring容器中对应的key是类名首字母小写。

    2、在spring核心配置文件。通知Spring容器内部的【注解解析类】到指定的包下扫描所有绑定了@Compoent的类,并将这些类创建实例对象并保存到Spring容器中。

@Component
public class Student {
    
      public void sayHello(String name){
          System.out.println("hello "+name);
      }
}
       
       <!--
          1.这个标签提供一个[扫描位置]
          2.Spring容器到这个指定位置下扫描所有的类。
            如果类上修饰了
            @Component,@Controller,@Service,@Repository
            则表示当前类的实例对象需要由Spring容器来提供
       -->
       <context:component-scan base-package="com.pm.entity"/>
public class TestMain {
    /*
    * ApplicationContext的两个接口实现类
    *
    * 1.FileSystemXmlApplicationContext:创建Spring容器对象可以在当前计算机任意硬盘上读取指定的spring
    *  核心配置文件
    *
    * 2.ClassPathXmlApplicationContext:创建Spring容器对象只能在当前项目的编译路径下读取指定的核心配置文件
    *
    */
    @Test
    public void test1(){
        //1.获得Spring容器对象,Spring容器对象在创建时自动读取指定的Spring核心配置文件
        ApplicationContext spring =new ClassPathXmlApplicationContext("spring.xml");
        //2.向Spring容器对象索要Student类对象
        Student stu =(Student)spring.getBean("student");
        stu.sayHello("mike");
    }
​
    @Test
    public void test2(){
        //1.获得Spring容器对象,Spring容器对象在创建时自动读取指定的Spring核心配置文件
        ApplicationContext spring =new ClassPathXmlApplicationContext("spring.xml");
        //2.连续向Spring容器索要两个Student类型对象
        Student s1 = (Student)spring.getBean("student");
        Student s2 = (Student)spring.getBean("student");
        System.out.println("s1 = "+s1.toString());
        System.out.println("s2 = "+s2.toString());
​
    }
​
    @Test
    public void test3(){
        //1.获得Spring容器对象,Spring容器对象在创建时自动读取指定的Spring核心配置文件
        ApplicationContext spring =new ClassPathXmlApplicationContext("spring.xml");
        //2.获得Spring容器对象所管理的所有实例对象的key
        String  keys[]=spring.getBeanDefinitionNames();
        for(String key:keys){
            System.out.println("key = "+key);
        }
    }
}

三、如果通过注解的方式向Spring容器索要DI服务:

  • 1、用于索要DI服务的两个注解

    • @Value:这个注解修饰在某个基本属性上。通知Spring容器对当前基本类型属性进行赋值,这个注解也可以修饰时在基本类型属性关联的set方法上。

      此外如果这个注解修饰在基本属性上,此时这个基本属性可以不用声明set方法。

      @Value注解出现的类必须修饰@Component,@Controller,@Service,@Repository中的一种注解。

@Component
public class Student {
​
     @Value("10")
     private int sid;
     @Value("smith")
     private String sname;
    
     private int age;
    @Override
    public String toString() {
        return "Student{" +
                "sid=" + sid +
                ", sname='" + sname + '\'' +
                ", age=" + age +
                '}';
    }
}
 <context:component-scan base-package="com.pm.pack1"/>
public class TestMain {
​
    @Test
    public void test1(){
        ApplicationContext spring =
                new ClassPathXmlApplicationContext("pack1/spring.xml");
       Student stu =(Student) spring.getBean("student");
        System.out.println(stu.toString());
    }
}
test1结果:Student{sid=10, sname='smith', age=0}

2、@AutoWired:这个注解修饰在应用类型属性上,通知Spring容器对象使用容器内部与之匹 配的对象,为当前属性进行赋值。这个注解也可以修饰在引用类型属性关联的set方法上。 此外如果这个注解修饰在基本属性上,此时这个基本属性可以不用声明set方法。

@AutoWired注解出现的类必须修饰@Component,@Controller,@Service,@Repository 中的一种注解。

@Component
public class School {
    @Value("北京大学")
    private String schoolName;
​
    public void setSchoolName(String schoolName) {
        this.schoolName = schoolName;
    }
​
    @Override
    public String toString() {
        return "School{" +
                "schoolName='" + schoolName + '\'' +
                '}';
    }
}
//=====================================================================
@Component
public class Student {
​
    @Value("10")
   private int sid;
    @Value("smith")
   private String sname;
​
    //默认情况下要求Spring容器按照类型进行匹配
    @Autowired
   private School myScool;
​
    @Override
    public String toString() {
        return "Student{" +
                "sid=" + sid +
                ", sname='" + sname + '\'' +
                ", myScool=" + myScool +
                '}';
    }
}
<context:component-scan base-package="com.pm.pack2"/>
public class TestMain {
​
    @Test
    public void test2(){
        ApplicationContext spring =
                new ClassPathXmlApplicationContext("pack2/spring.xml");
        Student stu =(Student)spring.getBean("student");
        System.out.println(stu.toString());
    }
}
test2结果:Student{sid=10, sname='smith', myScool=School{schoolName='北京大学'}}

四、JDK动态代理设计模式

  • JDK动态代理设计模式:简化对某个结构下所有的实现类进行同意修改,或者统一功能新增的开发难度。

  • 1、面向切面:

    • 切面对象来自于InvacationHandler接口实现类的实例对象;

    • 切面对象负责实现【新增统一功能】;

    • 负责接口上实现类中原有的方法与【新增功能】联合调用规则。

  • 2、代理对象:

    • 代理对象由JDK中工具类Proxy负责生产

    • 代理对象用于监听指定接口下某个实现类的实例对象

    • 在项目运行时,如果代理对象监听到程序需要被监听对象进行调用执行时,代理对象负责通知切面对象处理本次请求

      • 代理对象相当于监听事件

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值