• 自动装配


    ### 1. 自动装配:Autowire

    自动装配是一种自动为Bean的属性注入值的做法!

    假设存在`Student`类:

    public class Student {
        
            private City from;
        
            public City getFrom() {
                return from;
            }
        
            public void setFrom(City from) {
                this.from = from;
            }
        
        }

    类的属性希望被自动的注入值,则应该配置它的`autowire`属性:

    <bean id="student"
            class="cn.tedu.spring.Student"
            autowire="default">
        </bean>

    关于`autowire`属性,取值可以是`byName`,表示**根据名称实现自动装配**,即:要求类中的属性名与被装配进来的Bean的id保持一致(其实本质上还是通过SET方法注入的,要求的是SET方法的名称与Bean的id保持一致),所以:

        <bean id="from"
            class="cn.tedu.spring.City" />
        
        <bean id="student"
            class="cn.tedu.spring.Student"
            autowire="byName">
        </bean>

    自动装配其实是**尝试自动装配**,即:能够装配就装配,不能装配也不会报错!

    配置时,`autowire`属性的取值还可以是`byType`,即**根据类型实现自动装配**,Spring容器在尝试自动装配时,会在容器中(Spring管理的范围内)查找类型匹配的对象,如果没有,则不装配,如果有1个,则可以成功的自动装配,如果匹配类型的有2个或更多,则抛出异常`UnsatisfiedDependencyException`!

    除此以外,该属性还可以有其它取值,但是,通常,并不会在开发中使用该属性,因为它存在是否装配不明确的问题!而且,在实际开发中,其实自定义的Bean根本就不会在XML文件中配置,所以更加无处使用该属性!

    关于自动装配,重点理解`byName`和`byType`的特点。

    ### 2. 注解

    #### 2.1. 为什么要使用注解

    使用XML应用Spring时,需要使用大量的配置,导致代码的可读性较差(在阅读代码时,经常需要结合多个Java文件和XML配置一起查阅),并且,在XML配置中,如果出现拼写错误也不会实时提示错误信息!

    在实际使用时,会大量的使用注解,来取代XML中的配置!

    #### 2.2. 基本注解

    如果希望某个类被Spring管理,可以在类上添加`@Component`注解,并且,在Spring的配置文件中添加组件扫描的配置:

    <!-- 组件扫描 -->
        <!-- base-package:根包 -->
        <context:component-scan 
            base-package="cn.tedu.spring" />

    以上配置中的`base-package`用于指定组件所在的包,当加载该配置文件时,Spring框架会扫描指定的包,如果类之前添加了注解,则会被Spring管理。

    扫描的包之所以是`base-package`,表示各个类在其各层级的子包下,都会被扫描到,例如配置为`cn.tedu.spring`时,如果类是`cn.tedu.spring.dao.UserDao`,也是在扫描范围之内的!

    默认情况下,会使用类名且首字母改为小写作为Bean的id,所以,如果被Spring管理的是`Student`类,则默认的id就是`student`,当然,如果觉得默认的id命名不满足当前的应用需求,可以配置注解属性:

    @Component("stu")
        public class Student {
        }

    与`@Component`相同的注解还有:

    - `@Controller`:如果某个类在应用中起到的作用是控制器,则应该使用该注解
    - `@Service`:如果某个类在应用中起到的作用是业务逻辑类,则应该使用该注解
    - `@Repository`:如果某个类在应用中起到的作用是持久层处理(增删改查),则应该使用该注解

    其实,以上4个的作用、语法是完全相同的,只是语义不同,建议区分使用。

    #### 2.3. 【不常用】 作用域与生命周期的注解

    使用`@Scope`注解可以配置Bean的作用域,例如希望实现非单例效果时:

        @Component("stu")
        @Scope("prototype")
        public class Student extends Object {
        
        }

    在单例的情况下,如果需要单例模式是懒汉式的,则可以使用`@Lazy`注解:

    @Component("stu")
        @Lazy
        public class Student extends Object {
        
            public Student() {
                System.out.println("Student()");
            }
            
        }

    其实,`@Lazy`注解也可以配置属性值为`true`或`false`,但是,没有添加该注解时就是饿汉式的,添加该注解表示懒汉式且值为`true`,所以,不必配置属性值!

    关于生命周期方法:

        @PostConstruct
        public void init() {
            System.out.println("Student.init()");
        }
        
        @PreDestroy
        public void destroy() {
            System.out.println("Student.destroy()");
        }


    注意:以上2个注解是`javax`包中的注解,应该添加Tomcat或其它服务端环境。

    ### 2.4. 自动装配的注解

    假设存在`Student`类中的`public City from;`属性需要被装配值:

        @Component
        public class Student {
            public City from;
        }

    首先,`City`应该在Spring管理范围之内,即:需要在组件扫描范围之内,且添加了注解:

        package cn.tedu.spring;
    
        @Component
        public class City {
        }

    然后,在`Student`类的`from`属性之前,添加`@Autowired`注解即可:

    @Autowired
        public City from;


    与使用XML配置自动装配不同,注解方式的自动装配并不要求属性有SET方法,对属性的访问权限也没有要求,即使属性是私有的,也不影响装配过程!

    `@Autowired`注解是优先`byType`也可以byName!所以,要求匹配类型的Bean对象有且仅有1个(0个则无法装配,属性值为null,多个则直接抛出异常)!如果项目中确实有多个匹配类型的类,则只保留1个被Spring管理,其它的不由Spring管理即可,例如去掉类之前的`@Component`或相同作用的注解,或把这些类转移到组件扫描的包以外去。

    使用`@Resource`注解也可以实现自动装配,它是优先`byName`,如果失败,则会尝试`byType`。并且,使用`@Resource`时,如果一定要根据名称来装配,却存在名称不匹配的问题,可以在注解中配置名称:

    @Resource(name="city")
        public City from;

    以上`@Autowired`和`@Resource`都可以实现自动装配,在实际应用中,使用任何一个都可以!因为`@Resource`功能更强,所以很多人喜欢使用它,但是,并不是每个Java项目都是服务端项目,某些项目中可能并没有`javax`包中的内容,也就根本没有`@Resource`注解,就只能使用`@Autowired`,当然,这样的项目毕竟是少数,所以,在使用Java开发的Web应用程序中,使用这2种注解中的任何一个都是正确的做法!

    ### 2.5. 小结

    常用注解:

    - `@Controller`
    - `@Service`
    - `@Component`
    - `@Autowired` / `@Resource`

    非常用注解:

    - `@Repository`
    - `@Scope`
    - `@Lazy`
    - `@PostConstruct`
    - `@PreDetroy`

    ### 【附】 关于单例模式

        public class King {
            private static King king;
    
            private King() {
            }
    
            public static King getInstance() {
                synchronized("lock") {
                    if (king == null) {
                        king = new King();
                    }
                }
                return king;
            }
    
        }
  • 相关阅读:
    Linux零拷贝技术 直接 io
    纯Python模式
    c 越界 数组越界
    哈希 二叉树
    Cache busting
    sub esp
    lisp 代码即数据
    hexdump
    nmap
    对象 闭包
  • 原文地址:https://www.cnblogs.com/topzhao/p/10290738.html
Copyright © 2020-2023  润新知