Java – Spring – 基于注解管理Bean

简介

Spring 在2.5版之后,提出了基于注解进行管理Spring,关于使用XML管理Bean可参考以下文章:

简介 Spring IoC的其中一种管理实现,Spring 通过配置xml管理bean的方式。 所谓IoC,指的是我们的实现……
2023-01-03

 

@Component

传统xml配置Bean

使用传统xml方式配置Bean,通常我们可以使用<bean>标签进行配置

 <bean id=""                // Bean 的ID
          class=""          // Bean 的全类名
          name=""           // Bean 的别名
          abstract="true"   // 是否为
          autowire="byType" // 自动装配使用那种方式(以类型或ID)
          scope="singleton" // 作用域(单例或原型)
          lazy-init="true"  // 是否延迟加载
          factory-method="" // 静态工厂方法创建Bean
          factory-bean=""   // 实例工厂方法创建Bean
          init-method=""    // 实例工厂初始化方法
          destroy-method="" // 实例工厂销毁方法
/>

 

使用注解配置Bean对比

通过【@Component】注解,便可以让JavaBean类,作为Spring管理的Bean,如下

@Component("PersonService")
// 定义延迟加载
@Lazy(true)
// 定义作用域
@Scope("singleton")
public class PersonServiceImpl implements PersonService {

    // 定义 init-method 方法
    @PostConstruct
    public void init(){}

    // 定义 destroy-method 方法
    @PreDestroy
    public void destory(){}
}

1.因为【@Component】注解直接写在类定义上面,相当于完成xml中的【class】定义

 

 

2.【@Component】注解中,传入一个默认值【value】则是自定义Bean的ID,与xml中的【id】定义相同。如果不传入默认值,则id将被定义为【类名首写字母小写】的类名,如“personServiceImpl”

 

@Component 衍生注解

由于JavaEE开发是分层的,为了每层Bean标识的注解语义化更加明确,@Component 又衍生出如下三个注解

@Repository  : 在Dao层类上使用

@Service  : 在Service层类上使用

@Controller  : 在Web层类上使用

 

属性数据注入

类中有各种成员变量,在很多时候我们都需要为成员变量赋值。Spring提供了3+1一种数据注入的方式

传统xml注入

<bean id="" class="">
    <property name="" value=""></property>
    <property name="" ref=""></property>
</bean>

value 用于注入普通数据

 

ref 用于注入引用类型数据

 

使用注解注入

   // 使用在字段或方法上,用于注入普通数据
    @Value("#{systemProperties.myProp}")
    private String username;
    -------------------------------------------
    // 使用在字段或方法上,用于根据类型(byType)注入引用数据
    @Autowired
    private UserService userService;
    -------------------------------------------
    // 使用在字段或方法上,结合@Autowired,根据名称注入
    @Qualifier
    private UserService userService;
    -------------------------------------------
    // 结合@Autowired,强制根据名称注入相应的Bean
    @Autowired
    @Qualifier("userDao2")
    private UserDao userDao;
    -------------------------------------------
    // 使用在字段或方法上,根据类型或名称进行注入
    // 不指定名称时以类型注入,如果有名称,就根据名称注入
    @Resource(name="userService2")
    private UserService userService;
    -------------------------------------------
    @Value("${jdbc.username}")
    public void setUsername(String username){
        this.username = username;
    }
    -------------------------------------------

    // @Autowried 扩展一:set方法名随意
    // @Autowried 不以set方法为查找方法,可以使用任意方法,
    // 但是会依据传入的类型或形参名进行注入数据
    public void xxx(UserDao userDao){
       this.userDao = userDao;
    }
    -------------------------------------------
    // @Autowried 扩展二:传入Bean的List集合
    // 当Spring中存在多个相同类型的Bean时,@Autowried 可同时传入
    public void yyy(List<UserDao> userDaoList){
       ...会把Spring中的所有UserDao打包成List集合
    }

1.注入除了可以定义在成员变量上,也可以定义在set方法上。

2.@Autowried 注入set 方法时,可随意定义方法名,它以传入参数的类型和名称作为查找依据。

3.@Autowried 可注入 List 的Bean集合,当Spring中存在多个相同类型时,可以传递相同类型的集合。

 

非自定义Bean配置

当我们需要获取第三方对象作为Bean时,我们无法往第三方类中添加@Component 之类的注解,这时需要使用第三方Bean配置方式,使用【@Bean()】进行定义

@Bean()

@Component
public class OtherBean {

    // 如果 @Bean 定义了名称,则该第三方Bean的名称就为定义名
    // 如果 @Bean 没有定义名称,则该第三方Bean的名称为方法名
    @Bean("dataSource")
    public DataSource dataSource(
            // 形参内可以使用 @Value @Autowired @Qualifier 注入
            @Value("${jdbc.Driver}") String driverClassName,
            // 如果需要注入引用类型的数据,可以使用 @Autowired
            @Autowired Ref RefProp,
            // 如果需要强制使用名称定义注入的数据,可以添加 @Qualifier
            @Autowired @Qualifier("RefProp2") Ref RefProp2,
            // 在形参内,@Qualifier 可以省略 @Autowired 单独使用
            @Qualifier("RefProp3") Ref RefProp3,
            // 在形参内,如果该参数是引用类型的话,可以直接省略,Spring
            // 会按照参数名查找并进行注入
            Ref RefProp4
    ){
        DruidDataSource dataSource = new DruidDataSource();
        return dataSource;
    }

 

基于注解的配置项

通过以上的章节,我们知道如何使用注解来代替xml文件配置Bean,但是上面的章节中,使用的注解配置,是基于xml中配置<component-scan>标签实现的,若要完全脱离xml配置文件,我们同样可以使用注解的方式进行配置。

基本概念

如果我们使用xml文件作为Spring配置Bean的方式,那么我们必须创建一个xml文件作为配置的载体。

那么对于注解而言,我们如果使用注解来作为Spring配置Bean的方式,那么我们也必须创建一个类作为配置的载体。

可以把配置类,看作一个xml文件看待。

 

@Configuration

@Configuration 注解是用来描述用注解来配置的配置类声明,当类中加上@Configuration后,Spring就会认为这是一个配置类,它和@Component 类注解的区别在于,@Component 表示这个类是一个Bean,而@Configuration表示的是一个类似于applicationContext.xml文件的存在。

 

@ComponentScan

@ComponentScan 相当于xml文件中的 <context:component-scan/>标签,可以想象,<context:component-scan/>标签配置在xml文件中

相对的,@ComponentScan 注解,就应该配置在带有 @Configuration 注解的类中。

@Configuration
//<context:component-scan base-package="cn.unsoft"/>
@ComponentScan(basePackages = {"cn.unsoft"})
public class SpringAnnoConfig { }

basePackages 表示需要扫描的包目录的注解Bean,传入一个字符串数组,如果只有一个时,可以省略【{}】号。

 

同时 【basePackages】 也可以省略不写。

 

@PropertySource

@PropertySource 对应xml文件中的 <context:property-placeholder location="classpath:"/>标签

用于导入properties配置文件。

@Configuration
//<context:property-placeholder location="classpath:"/>
@PropertySource({"classpath:jdbc.properties"})
public class SpringAnnoConfig { }

 

@Import

@Import 对应xml中的<import resource="classpath:"/>,用于加载其它xml配置文件

@Import 是用于导入外部的其它配置类。如果需要加载其它xml配置文件的话,使用@ImportResource()

@Configuration
//<import resource="classpath:"/>
@Import({OtherConfig.class})
public class SpringAnnoConfig { }

 

@Import 重点技术

Spring与Mybatis注解方式整合有个重要的技术点是 @Import,第三方框架与Spring整合xml方式很多是凭借自定义标签完成的,而第三方框架与Spring整合注解方式很多是靠 @Import 注解完成的

@Import 可以导入如下三种类:

1.普通的配置类

2.实现ImportSelector接口的类

可以通过创建一个普通类,实现ImportSelector接口,ImportSelector接口提供了selectImports方法,该方法需要返回一个数组类型的String

返回类型表示需要被加入进BeanDefinitionMap中并实例化成Bean的全类名数组,可以在此提供需要创建为Bean的类,这种类可以完全是一个普通类,也就是说不需要带有 @Component 等注解的类也可以实现为Bean类。

public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"cn.unsoft.bean.xxx"};
    }
}

 

3.实现ImportBeanDefinitionRegistrar接口的类

可以通过创建一个普通类,实现ImportBeanDefinitionRegistrar接口,ImportBeanDefinitionRegistrar接口提供了registerBeanDefinitions方法,该方法可以通过BeanDefinitionRegistry 对象注册BeanDefinition对象,也就是需要我们自己去创建BeanDefinition,会把我们创建的BeanDefinition对象添加到BeanDefinitionMap中进行实例化Bean

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        BeanDefinition b = new RootBeanDefinition();
        b.setBeanClassName("");
        registry.registerBeanDefinition("beanName",b);
    }
}

 

 

@Primary

@Primary 注解用于标注相同类型的Bean优先被使用权,是Spring3.0后引入的,与@Component和@Bean一起使用,标注了的Bean优先级更高,则在通过类型获取Bean或通过@Autowrired根据类型进行注入时,会选月优先级更高的。

@Component("PersonService")
// 当存在多个相同类型的Bean时,使用类型注入时,标注了@Primary的Bean优先级更高
@Primary
public class PersonServiceImpl implements PersonService { }

 

@Profile

@Profile 注解的作用相当于xml文件中的环境切换标签

<beans profile="test">

在xml中配置 profile 后,在该<beans>的范围内,只有通过运行时使用 -Dspring.profiles.active=test 或使用代码设置当前运行环境 System.setProperty("spring.profiles.active","test")时,带有@Profile("test")的Bean类才会被执行。

@Component("PersonService")
// 当前的运行环境是 test 或 product 时,这个类才会被加载到Spring Bean中
@Profile({"test","product"})
public class PersonServiceImpl implements PersonService { }

 

通过注解整合第三方技术

整合Druid和Mybatis

在使用注解整合Druid和Mybatis技术之前,我们可以看一下通过xml方式整合的方式:

    <!--配置数据源-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="url" value="jdbc:mysq1://localhost:3306/mybatis"></property>
        <property name="username" value="root"></property>
        <property name="password" value="root"></property>
    </bean>
    <!--配置SqlSessionFactoryBean-->
    <bean class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!--配置Mapper包扫描-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.itheima.dao"></property>
    </bean>

 

实际上我们通过注解整合第三方技术,也只是通过xml的方式转化为一个类的方式:


@Configuration
@ComponentScan("cn.unsoft")
@PropertySource({"classpath:jdbc.properties"})
@MapperScan(basePackages = {"cn.unsoft.mapper"})
public class SpringAnnoConfig {

    /**
     * 使用注解配置 DataSource
     * 配置信息通过 @PropertySource 读取配置文件
     * 然后就可以通过 @Value 读取配置文件中的信息
     * @param driver
     * @param url
     * @param username
     * @param password
     * @return
     */
    @Bean
    public DataSource dataSource(
            @Value("${jdbc.driver}") String driver,
            @Value("${jdbc.url}") String url,
            @Value("${jdbc.username}") String username,
            @Value("${jdbc.password}") String password
    ){
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driver);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }


    /**
     * 使用注解配置 Mybatis Bean 并使用 DataSource
     * DataSource 通过上面的 DruidDataSource 创建
     * 在接收参数里,DataSource 本应该需要使用 @Autowired 进行装配的
     * 但是因为 DataSource 是引用类型,
     * 引用类型 Spring 会通过形参名进行搜索Bean并自动装配
     * 因此引用类型可以省略 @Autowired 注解
     * @param dataSource
     * @return
     */
    @Bean
    public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        return sqlSessionFactoryBean;
    }

    /**
     * 配置Mapper扫描
     * 配置Mapper扫描是Mybatis用于扫描那些包中有Mybatis的Mapper接口
     * 但是Mybatis提供了对应的扫描注解,因此不需要配置@Bean
     * 可查看本类类名上的 @MapperScan 注解
     */
}

 

 

如果您喜欢本站,点击这儿不花一分钱捐赠本站

这些信息可能会帮助到你: 下载帮助 | 报毒说明 | 进站必看

修改版本安卓软件,加群提示为修改者自留,非本站信息,注意鉴别

THE END
分享
二维码
打赏
海报
Java – Spring – 基于注解管理Bean
简介 Spring 在2.5版之后,提出了基于注解进行管理Spring,关于使用XML管理Bean可参考以下文章: Java – Spring – 基于XML管……
<<上一篇
下一篇>>