笔记:Bean管理的注解实现

传统的spring做法是使用.xml文件来对bean进行注入或者配置AOP、事务,这么做有两个缺点:

1、如果所有的内容都配置在.xml文件中,那么.xml文件将会十分庞大。如果按需求分开.xml文件,name.xml文件又会非常多。总之这将导致配置文件的可读性和可维护性变得很低。

2、在开发中.java文件和.xml文件之间的的不断切换,是一件很麻烦的事情,同时思维上的不连贯会降低开发效率

为了解决这两个问题,spring引入了 注解,通过“@xxx"的方式,让注解与java bean紧密结合,即减少了配置文件的体积,又增加了java bean的可读性。

基于类的注解:

@Component是一个通用注解,可用于任何bean

@Repository, @Service, @Controller是更有针对性的注解

  - @Repository通常用于注解DAO类,即持久层

  - @Service 通常用于注解Service类,即服务层

  - @Controller 通常用于注解Controller,即控制层(MVC)

类的自动检测及bean的注册

。spring可以自动检测类并注册bean到ApplicationContext中

//基于类的注解
@Service
public class SimpleMovieLister{
    private MovieFinder movieFinder;
    //方法和成员变量的注解,可以被spring自动检测到的
    @Autowired
    public SimpleMovieLister(MovieFinder movieFinder){
    this.movieFinder = movieFinder;
}
}

<context:annotation-config/>

。通过在基于xml的Spring配置如下标签

。<context:annotation-config/>仅会    查找在同一个application中的bean注解

<?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" >
   <context:annotation-config/>
</beans>
类的自动检测及Bean的注册

。为了能够检测这些类并注册相应的Bean,需要下面内容

<?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" >
   <context:component-scan base-package="com.example" />
</beans>

<context:component-scan/>会完成组件的扫描,基于类注解的这种扫描。扫描到类的注解,把这样的类注册到IOC容器中去。

base-package属性:扫描这个包下的所有类

<context:component-scan/>包含了 <context:annotation-config/>,通常使用前者后,不用在使用后者。


使用过滤器进行自定义的扫描

。默认情况下,类被自动发现并注册bean的条件是:使用@Component,@Repository,@Service,@Controller注解或者使用@Component的自定义注解

。可以通过过滤器修改上面的行为,如:下面例子的xml配置忽略所有的@Reponsitory注解并用”Stub“代替

<bean
    <context:component-scan base-backage="org.example">
//这是个包含的过滤器,类型regex是以通配符的形式来找stub和Responsitory这样的类
    <context:include-filter type="regex" expression=".*Stub.*Reponsitory"/>
//排除的过滤,类型是注解。排除所有用Responsitory来注解的类
  <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Responsitory"/>
</context:component-scan>
</bean>

。还可以使用use-default-filters="false" 禁止自动发现与注册

定义Bean

。扫描过程中组件被自动检测,那么bean名称是由BeanNameGenerator生成的(@Component,@Repository,@Service,@Controller都会有个name属性用于显示设置Bean Name)

//可以显式的指定这个类在注册到IOC容器中它所对应的类,相当于xml配置文件中的id
@Service"myMovieLister"
public class SimpleMovieLister{
    //...
}
//没有显式指定这个类的名称,它会根据BeanNameGenerator来自动生成它的id,
//规则是以类名为基础并把类名的第一个字母小写,把这个字符串作为bean的id
@Repository
public class MovieFinderImpl implements MovieFinder{
    //...
}

。可以自定义bean命名策略,实现BeanNameGenerator接口,并一定要包含一个无参构造器

<beans>
//使用自己定义的命名策略
    <context:component-scan base-package="org.example" name-generator="org.example.MyNameGenerator"/>
</beans
作用域(scope)

。通常情况下自动查找的Sring组件,其scope是singleton(单例模式),这样只会创建一个Action对象,每次访问都是同一个对象,数据不安全。@Scope("prototype")可以保证,当有请求的时候,都会创建一个Action对象

@Scope("prototype")
@Repository
public class MovieFinderImpl implements MovieFinder{
    //...
}

@Required

。@Required注解适用于bean属性的setter方法

。这个注解仅仅表示,受影响的bean属性必须在配置时被填充,通过在bean定义或通过自动装配一个明确的属性值

@Autowired

。比较常用,自动装配。可以将@Autowired注解为”传统“的setter方法

private MovieFinder movieFinder;

@Autowired
public void setMovieFinder(MovieFinder movieFinder){
    this.movieFinder=movieFinder;
}

。也可以用于构造器或成员变量

public class MovieRecommender{
    @Autowired
    private MovieCatalog movieCatalog;

    private CustomerDao cutomerDao;
    @Autowired
    public MovieRecommender(CustomerDao cutomerDao){
        this.cutomerDao=cutomerDao;
    }
}

。默认情况下,如果因找不到合适的bean将会导致autowiring失败抛出异常,可以通过设置@Autowired(required=false)。意思是:如果找不到bean的实例是不会抛出异常的,只有在使用的时候才会发现movieFinder是null。在使用的时候最好判断下是否为空。

public class SimpleMovieLister{
    private MovieFinder movieFinder;
    @Autowired(required=false)
    public void setMovieFinder(MovieFinder movieFinder){
    this.movieFinder=movieFinder;
    }
}

。每个类只能有一个构造器被标注为required=true;

。@Autowired的必要属性,建议使用@Required注解

。可以使用@Autowired注解哪些众所周知的解析依赖性接口,比如:BeanFactory,ApplicationContext,Environment,ResourceLoader,ApplicationEventPublisher,MessageSource

。可以通过添加注解给需要该类型的数组的字段或方法,以提供ApplicationContext中的所有特定类型的bean

private Set<MovieCatalog> movieCatalogs;
//可以注解在数组上,当前的ApplicationContext中所有是set泛型中声明的bean或它的子类都可以被@Autowired注解。
//然后把这些bean的实例都放到当前的结合当中去
@Autowired
public void setMovieCatalog(Set<MovieCatalog movieCatalogs){
    
    this.movieCatalogs = movieCatalogs;
}
。可以用于装配key为String的Map

。如果希望数组有序,可以让bean实现 org.springframeworke.core.Ordered接口或使用@Order注解

@Qualifier

。按类型自动装配多个bean实例的情况下,可以使用Spring的@Qualifier注解缩小范围(或指定唯一值),也可以用于指定单独的构造器参数或方法参数。

。可用于注解集合类型变量

。@Autowired适用于fields,constructor, multi-argument, methods这些允许在参数级别使用@Qualifier注解缩小范围的情况

。@Resource 适用于成员变量、只有一个参数的setter方法,所以在目标是构造器或一个多参数方法时,最好的方式是使用qualifiers

基于java容器的注解

。@Bean 标识一个用于配置和初始化一个由SpringIOC容器管理的新对象的方法,类似XML配置文件的<bean/>

。可以在Spring的@Component注解的类中使用@Bean注解任何方法

。通常和@Bean结合使用的是@Configuration,而不是@Component

@Configuration
public class AppConfig{
    @Bean
    public MyService myservice(){
        return new MyServiceImpl;
    }

}

相当于

<beans>
    <bean id="myService" class="com.services.MyServiceImpl"/>
</beans>

上面两个方法效果是一样的。

用@Bean注解方法,是以方法名为作为id

例:

public class Foo{
	public void init(){
		//init
	}
}
public class Bar{
	public void clearup(){
		//clearup
	}
}
@Configuration
public class AppConfig{
	@Bean(initMethod="init")
	public Foo foo(){
		return new Foo();
	}
	@Bean(destroyMethod="clearup")
	public Bar bar(){
		return new Bar();
	}
}


使用@ImportSource和@Value注解进行资源文件读取

spring配置Datasource,建立连接是只要有连接就新建一个connection,没有连接池的作用。

<beans>
<context:annotation-config/>
        //加载资源文件的配置
        <context:property-placeholder location="classpath:/com/acme/jdbc.properties"/>

        <bean class="com.acme.AppConfig"></bean>
        
        <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource">
                //获取properties文件的内容 通过键"url" 获取其value的内容
        	<property name="url" value="${jdbc.url}"/>
        	<property name="username" value="${jdbc.username}"/>
        	<property name="password" value="${jdbc.password}"/>
       </bean>
</beans>

使用注解配置

@Configuration
@ImportResource("classpath:/com/acme/properties-config.xml")
public class AppConfig{
	@Value("${jdbc.url}")
	private String url;
	
	@Value("${jdbc.username}")
	private String username;
	
	@Value("${jdbc.password}")
	private String password;
	
	@Bean
	public DataSource dataSource(){
		return new DriverManagerDataSource(url,username,password);
	}
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值