ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

(二)Spring-bean的作用域、xml和注解方式自动装配以及注解开发

2022-05-10 18:31:55  阅读:182  来源: 互联网

标签:xml name 作用域 org bean context import 注解 public


(二)Spring-bean的作用域、xml和注解方式自动装配以及注解开发

一、 bean的作用域

1.1 定义

当您创建一个 bean 定义时,您创建了一个用于创建由该 bean 定义定义的类的实际实例的方法。bean 定义是一个配方的想法很重要,因为这意味着,与一个类一样,您可以从一个配方创建许多对象实例。

  • 您不仅可以控制要插入到从特定 bean 定义创建的对象中的各种依赖项和配置值,还可以控制从特定 bean 定义创建的对象的范围。

  • 这种方法功能强大且灵活,因为您可以通过配置选择您创建的对象的范围,而不必在 Java 类级别定义对象的范围。可以将 Bean 定义为部署在多个范围之一中。Spring 框架支持六个范围,其中四个仅在您使用 web-aware 时可用ApplicationContext。您还可以创建 自定义范围。

1.2 六个作用域

Scope Description
singleton (Default) Scopes a single bean definition to a single object instance for each Spring IoC container.
prototype Scopes a single bean definition to any number of object instances.
request Scopes a single bean definition to the lifecycle of a single HTTP request. That is, each HTTP request has its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring ApplicationContext.
session Scopes a single bean definition to the lifecycle of an HTTP Session. Only valid in the context of a web-aware Spring ApplicationContext.
application Scopes a single bean definition to the lifecycle of a ServletContext. Only valid in the context of a web-aware Spring ApplicationContext.
websocket Scopes a single bean definition to the lifecycle of a WebSocket. Only valid in the context of a web-aware Spring ApplicationContext.

1 单例模式

spring默认机制

<bean id="accountService" class="com.something.DefaultAccountService"/>

<!-- the following is equivalent, though redundant (singleton scope is the default) -->
<bean id="accountService" class="com.something.DefaultAccountService" scope="singleton"/>

2 原型模式

每次从容器get的时候,都会产生一个新的对象!

<bean id="accountService" class="com.something.DefaultAccountService" scope="prototype"/>

3 其余的request,session,application

这些个只能在web 开发中使用的。

二、bean使用xml自动装配

2.1 定义

  • bean装配是spring满足bean依赖的一种方式!
  • spring会在上下文中自动寻找,并自动给bean装配属性!

2.2 spring中3种装配方式

  1. 在xml中显示的配置
  2. 在java中显示配置
  3. 隐式的自动装配bean【重要】

2.3 手动装配VS自动装配

2.3.1 手动装配

package com.happy.pojo;


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor@AllArgsConstructor
public class People {

    private String name;
    private Dog dog;
    private Cat cat;
}

package com.happy.pojo;

public class Cat {

    public void shout(){
        System.out.println("miao miao~");
    }
}

package com.happy.pojo;

public class Dog {
    public void shout(){
        System.out.println("wong wong ~");
    }
}

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


    <bean id="dog" class="com.happy.pojo.Dog"></bean>
    <bean id="cat" class="com.happy.pojo.Cat"></bean>
    <bean id="people" class="com.happy.pojo.People">
        <property name="name" value="happy"></property>
        <property name="dog" ref="dog"></property>
        <property name="cat" ref="cat"></property>
    </bean>
</beans>

测试使用

package com.happy.service;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.happy.pojo.People;
public class PeoPleService {


    @Test
    public void test() {
        ApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml");
        People people = context.getBean("people", People.class);
        System.out.println(people);
        people.getDog().shout();
    }
}

2.3.2 自动装配

1 ByName

注意:Byname是要保证,待装配对象的set方法和beanid一致,而并非待装配对象的属性名。

package com.happy.pojo;


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;


public class People {

    private String name;
    private Dog dog1;
    private Cat cat;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Dog getDog() {
        return dog1;
    }

    public void setDog(Dog dog) {
        this.dog1 = dog;
    }

    public Cat getCat() {
        return cat;
    }

    public void setCat(Cat cat) {
        this.cat = cat;
    }


    @Override
    public String toString() {
        return "People{" +
                "name='" + name + '\'' +
                ", dog1=" + dog1 +
                ", cat=" + cat +
                '}';
    }
}

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


    <bean id="dog" class="com.happy.pojo.Dog"></bean>
    <bean id="cat" class="com.happy.pojo.Cat"></bean>

<!--    ByName:会自动在容器上下文中查找,和自己对象set方法后面的值对应的bean-id-->
    <bean id="people" class="com.happy.pojo.People" autowire="byName">
    </bean>
</beans>
2 ByType

注意:

  • byType有自己的弊端,必须待装配对象的属性的类型保证在上下文里唯一
  • byType的依赖属性可以不用id都可以。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


    <bean id="dog" class="com.happy.pojo.Dog"></bean>
    <bean class="com.happy.pojo.Cat"></bean>

    <!--    ByType:会自动在容器上下文中查找,和自己对象属性类型相同的bean-id-->
    <bean id="people" class="com.happy.pojo.People" autowire="byType">

    </bean>
</beans>

2.4 总结

  • byName的时候,需要保证所有bean的id唯一,并且这bean需要和自动注入的set方法后面的名字一致。
  • byType的时候,需要保证所有bean的class唯一,并且这bean需要和自动注入属性的类型一致。

三、bean使用注解自动装配

3.1 使用条件

前提:

  • 和xml一样,所有依赖的类型都必须在xml即context中有了。

  • jdk1.5,spring2.5以后支持注解。

导入约束和注解支持<context:annotation-config/>

要使用注解须知:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

    <context:annotation-config/>

</beans>

实现如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/beans/spring-context.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/beans/spring-aop.xsd">


    <bean id="dog" class="com.happy.pojo.Dog"></bean>
    <bean id="cat" class="com.happy.pojo.Cat"></bean>

    <bean id="people" class="com.happy.pojo.People"></bean>
</beans>

3.2 @Autowired

  • 直接在属性上使用即可,可以在属性和set方法上注入,相当于xml得到property

  • 使用Autowired我们可以不用编写set方法了,前提是你这个自动装配的属性已经在IOC容器中存在,且符合按照ByType注入。

  • 先按照type找相同类型的bean注入,如果容器中存在两个以上相同的,再按照set后面的name进行注入。即先ByType再ByName

  • 如果ByType再ByName都存在两个以上(ByName没有找到相同的),则需要使用@Qualifier

3.3 @Qualifier

  • 自动装配属性的时候,在容器中存在两个相同的type能匹配上,又不能匹配name,则需要使用这个注解。
  • 即如果自动装配的环境比较复杂,自动装配无法通过一个注解@Autowired完成的时候,我们可以通过Autowired和Qualifier配合使用,就能指定一个唯一的bean对象注入
package com.happy.pojo;


import com.sun.istack.internal.NotNull;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;


public class People {


    private String name;
    @Autowired
    @Qualifier(value = "dog2")
    private Dog dog;
    @Autowired
    private Cat cat;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @NotNull
    public Dog getDog() {
        return dog;
    }
    @Nullable
    public void setDog(@NotNull Dog dog) {
        this.dog = dog;
    }

    public Cat getCat() {
        return cat;
    }

    public void setCat(Cat cat) {
        this.cat = cat;
    }


    @Override
    public String toString() {
        return "People{" +
                "name='" + name + '\'' +
                ", dog=" + dog +
                ", cat=" + cat +
                '}';
    }
}

3.4 @Resource

@Resource=@Autowired+@Qualifer

package com.happy.pojo;


import com.sun.istack.internal.NotNull;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;

import javax.annotation.Resource;


public class People {


    private String name;
    //    @Autowired
//    @Qualifier(value = "dog2")
    @Resource(name = "dog2")
    private Dog dog;
    @Autowired
    private Cat cat;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @NotNull
    public Dog getDog() {
        return dog;
    }

    @Nullable
    public void setDog(@NotNull Dog dog) {
        this.dog = dog;
    }

    public Cat getCat() {
        return cat;
    }

    public void setCat(Cat cat) {
        this.cat = cat;
    }


    @Override
    public String toString() {
        return "People{" +
                "name='" + name + '\'' +
                ", dog=" + dog +
                ", cat=" + cat +
                '}';
    }
}

3.5 Autowired vs @Resource

Autowired Resource
相同点 自动装配 自动装配
不同点 先type后name 先name后type

四、使用注解开发

4.1 使用条件

  • 在Spring4之后,要使用注解开发,必须要保证aop的包导入了。

  • 使用注解还需要导入context命名空间和约束,增加注解的支持!
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <context:annotation-config></context:annotation-config>
    <context:component-scan base-package="com.happy.pojo"></context:component-scan>
</beans>

导入约束和注解支持<context:annotation-config/>

  • 注解驱动,加上这个就可以使用resource这些注解了

导入包扫描标签</context:component-scan>

  • 扫描包
  • 配置该标签后,如果除了这个包没有在其他地方注解了,就不需要再配置context:annotation-config

4.2 bean

4.2.1 @Component

  • 将component放在类上,说明这个类被Spring 容器管理了,这就是bean。
  • 相当于<bean id="user" class="com.happy.pojo.User"></bean>
package com.happy.pojo;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;

/*<!--   <bean id="user" class="com.happy.pojo.User"></bean>-->*/
@Component
public class User {

    public String name ="高兴";

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }

    @Test
    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml");
        User user = context.getBean("user",User.class);
        System.out.println(user);
    }
}

4.3 属性如何注入

4.3.1 @Value

  • @value注入可以不用set方法
  • 相当于<property name="name" value="happybyxml"></property>
  • 复杂类型,如map,list等还是建议用xml注入属性,而不用注解
package com.happy.pojo;

import org.junit.Test;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;

/*<!--   <bean id="user" class="com.happy.pojo.User"></bean>-->*/
@Component
public class User {

    @Value("happy518")
    public String name ;

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }

    @Test
    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml");
        User user = context.getBean("user",User.class);
        System.out.println(user);
    }
}

4.3 衍生的注解

  • @Component有几个衍生注解,我们再web开发中,会按照mvc三层架构分层。
  • 这3个注解和@Component是等价的,人为定义@Component以后是注解非这3个注解的bean上

4.3.1 Dao层->@Repository

package com.happy.dao;

import org.springframework.stereotype.Repository;

@Repository
public class UserDao {
}

4.3.2 Service层->@Service

package com.happy.dao;

import org.springframework.stereotype.Repository;

@Repository
public class UserDao {
}

4.3.3 Controller层->@Controller

package com.happy.controller;

import org.springframework.stereotype.Controller;

@Controller
public class UserController {
}

4.4 自动装配置

见第三章节。

4.5 作用域

@Scope

package com.happy.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Scope;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;

/*<!--   <bean id="user" class="com.happy.pojo.User"></bean>-->*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Component
//@Scope("singleton")
@Scope("prototype")
public class User {

    @Value("happy518")
    public String name ;

}
package com.happy;

import com.happy.pojo.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class UserTest {
    
    @Test
    public void test() {
        ApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml");
//        单例模式,每次get为同一个对象
        User user1 = context.getBean("user", User.class);
        User user2 = context.getBean("user", User.class);
        System.out.println(user1 == user2);
    }

}

4.6 小结

XML vs 注解

Xml 注解
不同 xml更加万能,适用于任何场合! 注解:不是自己类使用不了
集中管理,维护简单 维护相对复杂
解耦 耦合较强

最佳实践:

  • xml用来管理bean
  • 注解负责完成属性注入
  • 我们再使用的过程中,只需要注意一个问题,必须要让注解生效,必须开启注解的支持

五、使用Java配置类

  • 使用java的方式配置spring,完全不用xml配置了,全权交给java来做

  • JavaConfig是Spring的一个子项目,在Spring 4之后,它成为另一个核心功能。

5.1 @Configuration介绍

1 使用和注册配置类

  • 在类上加上这个注解,代表该类是一个spring的配置类,等价于一个beans的application-context.xml文件。

  • 会被spring容器托管,注册到容器中,因为他本身也是一个component。

2 使用配置类注册bean

  • 注册一个bean,就相当于我们之前写的一个bean标签
  • 配置类中的方法名字,就相当于bean标签中的id属性。
  • 这个方法的返回类型,就相当于bean标签中的class属性。
  • 方法的返回对象就是要注入bean的对象

3 获取容器

  • 完全使用了配置类方式去做的方式,我们需要通过ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class)来获取容器了。

5.2 配置类使用步骤

1 实体类

package com.happy.pojo;

import lombok.Data;
import org.springframework.beans.factory.annotation.Value;

@Data
public class User {
    @Value("gaoxing")
    private String name;

}

2 配置类:

package com.happy.config;

import com.happy.pojo.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

@Configuration
//@Component
//@ComponentScan("com.happy.pojo")
public class MyConfig {

    @Bean
    public User getUser(){
        return new User();
    }
}

3 测试类

package com.happy;

import com.happy.config.MyConfig;
import com.happy.pojo.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class UserTest {

    @Test
    public void test(){
        ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
        User user = (User) context.getBean("getUser");
        System.out.println(user);
    }
}

这种纯java的配置方式,在SpringBoot中随处可见!

标签:xml,name,作用域,org,bean,context,import,注解,public
来源: https://www.cnblogs.com/happycarpediem/p/16254783.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有