spring中bean配置和bean注⼊
1 bean与spring容器的关系
Bean配置信息定义了Bean的实现及依赖关系,Spring容器根据各种形式的Bean配置信息在容器内部建⽴
Bean定义注册表,然后根据注册表加载、实例化Bean,并建⽴Bean和Bean的依赖关系,最后将这些准备就绪的Bean放到Bean缓存池中,以供外层的应⽤程序进⾏调⽤。
1 bean配置
bean配置有三种⽅法:
基于xml配置Bean
使⽤注解定义Bean
基于java类提供Bean定义信息
1.1 基于xml配置Bean
对于基于XML的配置,Spring 2.0以后使⽤Schema的格式,使得不同类型的配置拥有了⾃⼰的命名空间,是配置⽂件更具扩展性。
①默认命名空间:它没有空间名,⽤于Spring Bean的定义;
②xsi命名空间:这个命名空间⽤于为每个⽂档中命名空间指定相应的Schema样式⽂件,是标准组织定
义的标准命名空间;
③aop命名空间:这个命名空间是Spring配置AOP的命名空间,是⽤户⾃定义的命名空间。
命名空间的定义分为两个步骤:第⼀步指定命名空间的名称;第⼆步指定命名空间的Schema⽂档样式⽂件的位置,⽤空格或回车换⾏进⾏分分隔。
1.1.1 Bean基本配置
在Spring容器的配置⽂件中定义⼀个简要Bean的配置⽚段如下所⽰:
⼀般情况下,Spring IOC容器中的⼀个Bean即对应配置⽂件中的⼀个<bean>,这种镜像对应关系应该容易理解。其中id为这个Bean的名称,通过容器的getBean("foo")即可获取对应的Bean,在容器中起到
定位查的作⽤,是外部程序和Spring IOC容器进⾏交互的桥梁。class属性指定了Bean对应的实现类。
下⾯是基于XML的配置⽂件定义了两个简单的Bean:
<?xml version="1.0" encoding="UTF-8" ?>
<beans  xmlns="/schema/beans"
xmlns:xsi="/2001/XMLSchema-instance"
xsi:schemaLocation="/schema/beans
/schema/beans/spring-beans-3.0.xsd">
<bean id="car" name="#car1" class="com.baobaotao.simple.Car"></bean>
<bean id="boss" class="com.baobaotao.simple.Boss"></bean>
</beans>
1.1.2 依赖注⼊
1. 属性注⼊
2. 构造函数注⼊
3. ⼯⼚⽅式注⼊
1.2 使⽤注解定义Bean
我们知道,Spring容器成功启动的三⼤要件分别是:Bean定义信息、Bean实现类以及Spring本⾝。如果采⽤基于XML的配置,Bean定义信息和Bean实现类本⾝是分离的,⽽采⽤基于注解的配置⽅式时,Bean定义信息即通过在Bean实现类上标注注解实现。
下⾯是使⽤注解定义⼀个DAO的Bean:
package com.baobaotao.anno;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
//①通过Repository定义⼀个DAO的Bean
@Component("userDao")
public class UserDao {
}
在①处,我们使⽤@Component注解在UserDao类声明处对类进⾏标注,它可以被Spring容器识别,Spring容器⾃动将POJO转换为容器管理的Bean。
它和以下的XML配置是等效的:
<bean id="userDao" class="com.baobaotao.anno.UserDao"/>
除了@Component以外,Spring提供了3个功能基本和@Component等效的注解,它们分别⽤于对DAO、Service及Web层的Controller进⾏注解,所以也称这些注解为Bean 的衍型注解:(类似于xml⽂件中定义Bean<bean id=" " class=" "/>
@Repository:⽤于对DAO实现类进⾏标注;
@Service:⽤于对Service实现类进⾏标注;
@Controller:⽤于对Controller实现类进⾏标注;
之所以要在@Component之外提供这三个特殊的注解,是为了让注解类本⾝的⽤途清晰化,此外Spring将赋予它们⼀些特殊的功能。
1.2.1 使⽤注解配置信息启动spring容器
Spring提供了⼀个context的命名空间,它提供了通过扫描类包以应⽤注解定义Bean的⽅式:
<?xml version="1.0" encoding="UTF-8" ?>
<!--①声明context的命名空间-->
<beans xmlns="/schema/beans"
xmlns:xsi="/2001/XMLSchema-instance"
xmlns:context="/schema/context"
xsi:schemaLocation="/schema/beans
/schema/beans/spring-beans-3.0.xsd
/schema/context
/schema/context/spring-context-3.0.xsd"
>
<!--②扫描类包以应⽤注解定义的Bean-->
<context:component-scan base-package="com.baobaotao.anno"/>
<bean class="com.baobaotao.anno.LogonService"></bean>
<!-- context:component-scan base-package="com.baobaotao" resource-pattern="anno/*.class"/ -->
<!-- context:component-scan base-package="com.baobaotao">
<context:include-filter type="regex" expression="com\.baobaotao\.anno.*Dao"/>
<context:include-filter type="regex" expression="com\.baobaotao\.anno.*Service"/>
<context:exclude-filter type="aspectj" expression="com.baobaotao..*Controller+"/>
</context:component-scan -->
</beans>
在①处声明context命名空间,在②处即可通过context命名空间的component-scan的base-package属性指定⼀个需要扫描的基类包,Spring容器将会扫描这个基类包⾥的所有类,并从类的注解信息中获取Bean的定义信息。
如果仅希望扫描特定的类⽽⾮基包下的所有类,你们可以使⽤resource-pattern属性过滤特定的类,如下所⽰:
< context:component-scan base-package="com.baobaotao" resource-pattern="anno/*.class"/ >
这⾥我们将基类包设置为com.baobaotao,默认情况下resource-pattern属性的值为"**/*.class",即基类包⾥的所有类。这⾥我们设置为"anno/*.class",则Spring仅会扫描基包⾥anno⼦包中的类。
1.3 基于java类提供Bean定义
在普通的POJO类中只要标注@Configuration注解,就可以为spring容器提供Bean定义的信息了,每个标注了@Bean的类⽅法都相当于提供了⼀个Bean的定义信息。
package f;
import t.annotation.Bean;
import t.annotation.Configuration;
//①将⼀个POJO标注为定义Bean的配置类
@Configuration
public class AppConf {
//②以下两个⽅法定义了两个Bean,以提供了Bean的实例化逻辑
@Bean
public UserDao userDao(){
return new UserDao();
}
@Bean
public LogDao logDao(){
return new LogDao();
}
//③定义了logonService的Bean
@Bean
public LogonService logonService(){
LogonService logonService = new LogonService();
//④将②和③处定义的Bean注⼊到LogonService Bean中
logonService.setLogDao(logDao());
logonService.setUserDao(userDao());
return logonService;
}
}
①处在APPConf类的定义处标注了@Configuration注解,说明这个类可⽤于为Spring提供Bean的定义信息。类的⽅法处可以标注@Bean注解,Bean的类型由⽅法返回值类型决定,名称默认和⽅法名相同,也可以通过⼊参显⽰指定Bean名称,如@Bean(name="userDao").直接在@Bean所标注的⽅法中提供Bean的实例化逻辑。
在②处userDao()和logDao()⽅法定义了⼀个UserDao和⼀个LogDao的Bean,它们的Bean名称分别是userDao和logDao。在③处,⼜定义了⼀个logonService Bean,并且在④处注⼊②处所定义的两个Bean。
因此,以上的配置和以下XML配置时等效的:
<bean id="userDao" class="com.baobaotao.anno.UserDao"/>
<bean id="logDao" class="com.baobaotao.anno.LogDao"/>
<bean id="logService" class="f.LogonService"
p:logDao-ref="logDao" p:userDao-ref="userDao"/>
基于java类的配置⽅式和基于XML或基于注解的配置⽅式相⽐,前者通过代码的⽅式更加灵活地实现了Bean的实例化及Bean之间的装配,但后⾯两者都是通过配置声明的⽅式,在灵活性上要稍逊⼀些,但是配置上要更简单⼀些。
2 Bean注⼊
Bean注⼊的⽅式有两种,⼀种是在XML中配置,此时分别有属性注⼊、构造函数注⼊和⼯⼚⽅法注⼊;另⼀种则是使⽤注解的⽅式注⼊。
2.1 在xml⽂件中配置依赖注⼊
2.1.1 属性注⼊
属性注⼊即通过setXxx()⽅法注⼊Bean的属性值或依赖对象,由于属性注⼊⽅式具有可选择性和灵活性⾼的优点,因此属性注⼊是实际应⽤中最常采⽤的注⼊⽅式。
属性注⼊要求Bean提供⼀个默认的构造函数,并为需要注⼊的属性提供对应的Setter⽅法。Spring先调⽤Bean的默认构造函数实例化Bean对象,然后通过反射的⽅式调⽤Setter⽅法注⼊属性值。
package com.baobaotao.anno;
import org.springframework.beans.factory.BeanNameAware;
public class LogonService implements BeanNameAware{
private LogDao logDao;
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void setLogDao(LogDao logDao) {
this.logDao = logDao;
}
public LogDao getLogDao() {
return logDao;
}
public UserDao getUserDao() {
return userDao;
}
public void setBeanName(String beanName) {
System.out.println("beanName:"+beanName);
}
public void initMethod1(){
System.out.println("initMethod1");
}
public void initMethod2(){
System.out.println("initMethod2");
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="/schema/beans"
xmlns:xsi="/2001/XMLSchema-instance"
xmlns:context="/schema/context"
xsi:schemaLocation="/schema/beans
/schema/beans/spring-beans-3.0.xsd
/schema/context
/schema/context/spring-context-3.0.xsd"
default-autowire="byName"
>
<bean id="logDao" class="com.baobaotao.anno.LogDao"/>
<bean id="userDao" class="com.baobaotao.anno.UserDao"/>
<bean class="com.baobaotao.anno.LogonService">
<property name="logDao" ref="logDao"></property>
<property name="userDao" ref="userDao"></property>
</bean>
</beans>
2.1.2 构造⽅法注⼊
使⽤构造函数注⼊的前提是Bean必须提供带参数的构造函数。例如
package com.baobaotao.anno;
import org.springframework.beans.factory.BeanNameAware;
public class LogonService implements BeanNameAware{
public LogonService(){}
public LogonService(LogDao logDao, UserDao userDao) {
this.logDao = logDao;
this.userDao = userDao;
}
private LogDao logDao;
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void setLogDao(LogDao logDao) {
this.logDao = logDao;
}
public LogDao getLogDao() {
return logDao;
}spring framework和spring的关系
public UserDao getUserDao() {
return userDao;
}
public void setBeanName(String beanName) {
System.out.println("beanName:"+beanName);
}
public void initMethod1(){
System.out.println("initMethod1");
}
public void initMethod2(){
System.out.println("initMethod2");
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="/schema/beans"
xmlns:xsi="/2001/XMLSchema-instance"
xmlns:context="/schema/context"
xsi:schemaLocation="/schema/beans
/schema/beans/spring-beans-3.0.xsd
/schema/context
/schema/context/spring-context-3.0.xsd"
default-autowire="byName">
<bean id="logDao" class="com.baobaotao.anno.LogDao"/>
<bean id="userDao" class="com.baobaotao.anno.UserDao"/>
<bean class="com.baobaotao.anno.LogonService">
<constructor-arg  ref="logDao"></constructor-arg>
<constructor-arg ref="userDao"></constructor-arg>
</bean>
</beans>
2.1.3 ⼯⼚⽅法注⼊
⾮静态⼯⼚⽅法:
有些⼯⼚⽅法是⾮静态的,即必须实例化⼯⼚类后才能调⽤⼯⼚放。
package com.baobaotao.ditype;
public class CarFactory {
public Car createHongQiCar(){
Car car = new Car();
car.setBrand("红旗CA72");
return car;
}
public static Car createCar(){
Car car = new Car();
return car;
}
}
⼯⼚类负责创建⼀个或多个⽬标类实例,⼯⼚类⽅法⼀般以接⼝或抽象类变量的形式返回⽬标类实例,⼯⼚类对外屏蔽了⽬标类的实例化步骤,调⽤者甚⾄不⽤知道具体的⽬标类是什么。
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="/schema/beans"
xmlns:xsi="/2001/XMLSchema-instance"
xmlns:p="/schema/p"
xsi:schemaLocation="/schema/beans
/schema/beans/spring-beans-3.0.xsd">
<!-- ⼯⼚⽅法-->
<bean id="carFactory" class="com.baobaotao.ditype.CarFactory"/>
<bean id="car5" factory-bean="carFactory" factory-method="createHongQiCar">
</bean>

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。