spring入门学习-4、Bean装配(注解)

  • classpath扫描与组件管理

@Componmet是通用注解,可用于任何bean,是@Respository、@Service、@Controller的父注解,后三个注解更具有针对性。

  1. @Respository通常用于DAO,即持久层
  2. @Service通常用于Service,即业务层
  3. @Controller通常用于Controller,即控制层

Spring还可以自定义注解,利用元注解(元数据注解),比如@service注解的定义中用到了@Componmet,同时元注解还可以定义其他属性,例如:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Scope("session")
public @interface SessionScope {
    ScopedProxyMode proxyMode() default ScopedProxyMode.DEFAULT;
}

  • 类的自动检测与注册

1)配置文件中配置

要使用自动注解,首先在xml中配置包含上下文的命名空间,如下:

<?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
 http://www.springframework.org/schema/beans/spring-beans.xsd
 http://www.springframework.org/schema/context
 " >http://www.springframework.org/schema/context/spring-context.xsd">
</beans>

<context:annotation-config />

这个标签处理@autowired之类的注解(AutowiredAnnotationBeanPostProcessor、RequiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor以及PersistenceAnnotationBeanPostProcessor四个类) 前提是注解作用的类已经被注册到spring容器里

<context:component-scan base-package="com.xx.xx" />

除了包含annotation-config的作用外,还能自动扫描和注册base-package下有@component@Respository、@Service、@Controller之类注解的类,将其作为bean注册到spring容器里此配置包含annotation-config使用此配置可以不在使用annotation-config

a、使用过滤器自定义扫描

<?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
 http://www.springframework.org/schema/beans/spring-beans.xsd
 http://www.springframework.org/schema/context
 " >http://www.springframework.org/schema/context/spring-context.xsd">

<!--忽略所有@Repository注解使用Stub下的注解代替-->
    <context:component-scan base-package="test">
        <context:include-filter type="regex" expression=".*Stub.*Repository"></context:exclude-filter>
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"></context:exclude-filter>
    </context:component-scan>
</beans>

b、禁用自动注册与发现

use-default-filters="false"

2)使用注解标注

被@Respository、@Service、@Controller、@Controller等注解标注的类,spring会自动检测到bean并自动注册到ApplicationContext中。

①bean名称生成规则

扫描过程中组件被自动检测,那么bean名称由BeanNameGenerator生成(@Respository、@Service、@Controller、@Controller都有属性用于显性设置beanName),如果注解处线性设置name,那么注册到上下文中的beanName以显示设置为主,如果未设置,spring会将被注解标注的类名首字母小写作为bean在上下文中的名称。

②可自定义bean命名规则,需实现BeanNameGenerator接口,并一定要包含一个无参的构造函数,同时在xml文件中配置name-generator。

<context:component-scan base-package="test" name-generator="">
</context:component-scan>

  • 作用域(scope)

默认情况下spring组件是singleton模式,我们可以通过@Scope注解来自定义设置作用域类型(例如:@Scope("prototype"))。也可以自定义scope策略,实现ScopeMetadataResolver接口并创建无参构造函数。

<context:component-scan base-package="test" scope-resolver="">
</context:component-scan>

  • @Required注解

  1. 该注解适用于bean属性的setter方法。
  2. 表示受影响的bean属性必须在配置时被赋值。
  • @Autowired注解

@Autowired根据类型进行自动装配的。如果当spring上下文中存在不止一个同类型的bean时,会抛出异常,可以使用@Qualifier来指定名称。

@Autowired是由SpringBeanPostProcessor处理的,所以不能在自己的BeanPostProcessor或BeanFactoryPostPorcessor类型应用这些注解,这些类型必须通过使用XML或者@Bean注解加载。

①setter、构造、属性注入

此注解可用于setter方法、构造器、成员变量上,默认情况下如果找不到bean,会抛出异常,可以通过使用@Autowired(required=false)来避免。在使用@Autowired注解时,需要注意,每个类只有一个构造器允许被标记为@Autowired(required=true),如果要使用多个,可以使用@Required来代替。

@Service
public class InjectionServiceImpl implements InjectionService {
    //@Autowired属性注入
    private InjectionDAO injectionDAO;

//构造注入
    @Autowired
    public InjectionServiceImpl(InjectionDAO injectionDAO){
        this.injectionDAO = injectionDAO;
    }
    //@Autowired setter方法注入
    public void setInjectionDAO(InjectionDAO injectionDAO) {
        this.injectionDAO = injectionDAO;
    }
    public void say() {
        injectionDAO.doSomeThing();
        System.out.println("这里是Service方法.....");
    }
}

②解析依赖性接口

可以使用@Autowired解析依赖性接口,例如:BeanFactory、ApplicationContext、ResourceLoader等

@Component
public class MoviceRecommender {
    @Autowired
    private ApplicationContext context;

    public void analysisContext() {
        System.out.println("内容 : " + context.getId());
    }
}

③注入某类型的数组(List、Set等)和Map(key必须时String类型)

注入某类型的数组或Map时,spring会自动将数据组的类型注入,需要注意的时Map类型注入时,key必须时string类型,同时@order注解对map类型注入无效;

public interface BeanInterface {}

@Order(2)

@Component
public class BeanImpl1 implements BeanInterface {}

@Order(1)

@Component
public class BeanImpl2 implements BeanInterface {}

@Component
public class MutilBean{
    @Autowired
    private List<BeanInterface> list;
    @Autowired
    private Map<String,BeanInterface> map;
    public void say(){
        if (list != null){
            for (BeanInterface bean : list){
                System.out.println(bean.getClass().getSimpleName());
            }
        }else{
            System.out.println("list is null");
        }

        if(map != null){
            for (Map.Entry<String,BeanInterface> bean : map.entrySet() ){
                System.out.println(bean.getKey() +"   "+bean.getValue());
            }
        }else{
            System.out.println("map is null");
        }
    }
}

  • @Qualifier注解

如果spring上下文中存在多类型,无法使用@Autowired进行注入时,可以通过时用@Qualifier来标注具体注入的bean名称,@Qualifier除了在成员变量、构造器、setter方法上使用外,还可以使用在类型参数中,例如:

public void say(@Qualifier("name1") String name){}

@Resource也可以通过名称注入,适用于成员变量、只有一个参数的setter方法,所以在使用构造器或多参setter方法时,最好使用@Qualifier和@Autowired

  • 基于java的容器注解

1)@Bean注解

用于配置和初始化SpringIOC容器管理的新对象的方法类似于XML中<bean id="beanScope" class="com.base.java.test.BeanScope" ></bean>

配置,通常与@configuration配合使用,如何@Bean不指定名称,系统会按照@Bean所在的方法名标记为name。@Bean也可以指定initMethoddestroyMethod默认情况下@Bean默认情况下是单例的,可以使用@Scope来改变。

public class StringStore {
    public void init(){
        System.out.println("init...");
    }
    public void destory(){
        System.out.println("destory...");
    }
}

@Configuration
public class StoreConfig {
    @Bean(name="store",initMethod = "init",destroyMethod = "destory")
    public StringStore getStringStore(){
        return new StringStore();
    }
}

2)@Value和@ImportResource注解

这两个注解作用是引入配置资源文件,例如:

①创建资源文件名称db.properties,信息为:

jdbc.url=172.0.0.1
jdbc.driver=com.mysql.jdbc.Driver
jdbc.userName=root
jdbc.password=1234

②在配置文件中设置信息文件名context-db.xml,

<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
 http://www.springframework.org/schema/beans/spring-beans.xsd
 http://www.springframework.org/schema/context
 http://www.springframework.org/schema/context/spring-context.xsd">
    <context:property-placeholder location="db.properties"></context:property-placeholder>
</beans>

③创建Java类

public class MyDriverManager {
    public MyDriverManager(String url,String driver,String userName,String password){
        System.out.println("url : " +url);
        System.out.println("driver : " + driver);
        System.out.println("userName : " + userName);
        System.out.println("password : " + password);
    }
}

@Configuration
@ImportResource("classpath:context-db.xml")
public class DBStore {
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.userName}")
    private String userName;
    @Value("${jdbc.password}")
    private String password;
    @Bean
    public MyDriverManager myDriverManager(){//未指定名称,默认按方法名称注册
        return new MyDriverManager(url,driver,userName,password);
    }
}

使用applicationContext.getBean("myDriverManager")或注解获取信息。

此方式的xml配置方式如下:

<beans>
    <context:annotation-config/>
    <context:property-placeholder location="classpath:db.properties"/>
    <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.userName}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
</beans>

  • 基于泛型的自动装配(spring4.x以后支持)

本部分摘录:https://blog.csdn.net/u010837612/article/details/45582043

public class User {
}

public class Role {
}

public class BaseRepository<T> {
    public void add(){
        System.out.println("Repository add");
    }
}

public class BaseService<T> {
    @Autowired
    private BaseRepository<T> repository;

    public void add(){
        repository.add();
    }
}

@Repository
public class UserReponsitory extends BaseRepository<User> {
}

@Service
public class UserService extends BaseService<User> {
}

@Repository
public class RoleReponsitory extends BaseRepository<Role> {
}

@Service
public class RoleService extends BaseService<Role> {
}

public class Main {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-generic.xml");
        UserService userService = (UserService) ctx.getBean("userService");
        userService.add();
    }
}

Spring会根据泛型类型自动区分BaseService属于RoleService还是UserServiceUserService的父类和UserReponsitory的父类产生联系,那么通过泛型,UserServiceUserReponsitory也产生联系。此种方式适用于将重复的代码封装起来通过继承来简化代码,对代码进行复用。

  • @Resource注解

Spring还支持使用JSR-250@Resource注解,此注解可标记成员变量和setter方法,在Java EE5和6之后支持,由spring的CommonAnnotationBeanPostProcess这个类发现并处理的。这个还可以处理@PostConstruct(初始化)和@PreDestory(销毁)这两个注解。

@Resource注解可以指定name属性@Resource(name=""),如果不指定,对于成员变量spring会以变量名称解析,对于setter方法,spring会以方法名解析。

@Repository
public class JsrDao {
    public void save(){
        System.out.println("jsr dao save()..");
    }
}

@Service
public class JsrService{
    @Resource
    private JsrDao jsrDao;

    public void save(){
        jsrDao.save();
    }
    @PostConstruct
    public void init(){
        System.out.println("init");
    }
    @PreDestroy
    public void destory(){
        System.out.println("destory");
    }
}

  • JSR330标准注解

Spring3.0开始支持JSR330标准注解,扫描方式于spring注解一致,使用JSR330标准注解依赖javax.inject包。

①@Inject注解

这个注解等效于@Autowired,可适用于类、成员变量、方法、构造器。

②@Named注解

@Name注解与@Component注解是等效的,不同的是此注解可用于参数指定具体名称。

private JsrDao jsrDao;

@Inject
public void setJsrDao(@Named("jsrDao") JsrDao jsrDao){
    this.jsrDao = jsrDao;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值