Spring的Bean配置和装配
每个bean定义只生成一个对象实例,每次getBean请求获得的都是此实例
spring单例默认是饿汉模式
配置Bean——setter方法设置属性
<!-- 无属性bean -->
<!-- 如果不指明id,则会用全限定类名加上#序号命名 -->
<bean id="address" class="com.spring.xmlBean.Address"></bean>
<!-- 普通属性bean -->
<bean id="address" class="com.spring.xmlBean.Address">
<property name="city" value="日照"></property>
<property name="province" value="山东"></property>
</bean>
<!-- 通过ref引用其他bean作为属性 -->
<bean id="person" class="com.spring.xmlBean.Person">
<property name="name" value="Little-Koala"></property>
<property name="age" value="18"></property>
<property name="address" ref="address"></property>
</bean>
<!-- 属性为集合的bean -->
<bean id="complexAssembly"class="com.ssm.chapter10.pojo.ComplexAssembly">
<property name="id" value="1"/>
<property name="list">
<list>
<value>value-list-1</value>
<value>value-list-2</value>
</list>
</property>
<property name="map">
<map>
<entry key="key1" value="value-key-1"/>
<entry key="key2" value="value-key-2"/>
</map>
</property>
<property name="props">
<props>
<prop key="prop1">value-prop-1</prop>
<prop key="prop2">value-prop-2</prop>
</props>
</property>
<property name="set">
<set>
<value>value-set-1</value>
<value>value-set-2</value>
</set>
</property>
<property name="array">
<array>
<value>value-array-1</value>
<value>value-array-2</value>
</array>
</property>
<!-- 集合的涉及对象的bean装载 -->
<property name="list2">
<list>
<ref bean="role1"/>
<ref bean="role2"/>
</list>
</property>
<property name="map2">
<map>
<entry key-ref="role1" value-ref="user1"/>
<entry key-ref="role2" value-ref="user2"/>
</map>
</property>
<property name="set2">
<set>
<ref bean="role1"/>
<ref bean="role2"/>
</set>
</property>
</bean>
配置Bean——构造器初始化
<!-- 构造器普通参数 -->
<bean id="address" class="com.spring.xmlBean.Address">
<constructor-arg name="city" value="日照"></constructor-arg>
<constructor-arg name="province" value="山东"></constructor-arg>
</bean>
<!-- 构造器对象参数 -->
<bean id="person" class="com.spring.xmlBean.Person">
<constructor-arg name="name" value="Little-Koala"></constructor-arg>
<constructor-arg name="age" value="18"></constructor-arg>
<constructor-arg name="address" ref="address"></constructor-arg>
</bean>
<!-- 构造器也可以配置集合作为参数,格式类似与setter方法,这里不再列举 -->
命名空间
要使用命名空间需要在头部xml加入:
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
装配bean引用与装配字面量的唯一区别在于是否带有“-ref”后缀。如果没有“-ref”后缀的话,所装配的就是字面量
<bean id="hello2" class="com.app.Hello" p:p1="v1" p:p2="v2" p:world-ref="world"/>
<bean id="hello2" class="com.app.Hello" c:arg1="c_arg1" c:arg2="2" c:arg3-ref="world"/>
命名空间的属性无法实现装配集合的功能,解决方法就是util命名空间
<util:list id="userList" value-type="java.lang.String">
<value>张三</value>
<value>李四</value>
<value>王五</value>
</util:list>
<!-- 配置一个Map集合 -->
<util:map id="userMap">
<entry key="user1" value-ref="user" />
<entry key="user2">
<!-- 配置一个内部Bean -->
<bean class="io.shuqi.ssh.spring.util.User">
<property name="userAge" value="12" />
<property name="userName" value="小张" />
</bean>
</entry>
</util:map>
<!-- 命名空间中引用util命名空间 -->
<bean id="hello2" class="com.app.Hello" c:arg1="c_arg1" c:arg2="2" c:arg3-ref="list"/>
xml配置扫描路径
<!-- 扫描的基本包路径 -->
<!-- 是否激活属性注入注解 -->
<!-- Bean的ID策略生成器 -->
<!-- 对资源进行筛选的正则表达式,这边是个大的范畴,具体细分在include-filter与exclude-filter中进行 -->
<!-- scope解析器 ,与scoped-proxy只能同时配置一个 -->
<!-- scope代理,与scope-resolver只能同时配置一个 -->
<!-- 是否使用默认的过滤器,默认值true -->
<context:component-scan base-package="com.wjx.betalot"
annotation-config="true"
name-generator="org.springframework.context.annotation.AnnotationBeanNameGenerator"
resource-pattern="**/*.class"
scope-resolver="org.springframework.context.annotation.AnnotationScopeMetadataResolver"
scoped-proxy="no" use-default-filters="false">
<!-- 注意:若使用include-filter去定制扫描内容,要在use-default-filters="false"的情况下,不然会“失效”,被默认的过滤机制所覆盖 -->
<!-- annotation是对注解进行扫描 -->
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Component" />
<!-- assignable是对类或接口进行扫描 -->
<context:include-filter type="assignable"
expression="com.wjx.betalot.performer.Performer" />
<context:include-filter type="assignable"
expression="com.wjx.betalot.performer.impl.Sonnet" />
<!-- 注意:在use-default-filters="false"的情况下,exclude-filter是针对include-filter里的内容进行排除 -->
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
<context:exclude-filter type="assignable"
expression="com.wjx.betalot.performer.impl.RainPoem" />
<context:exclude-filter type="regex"
expression=".service.*" />
</context:component-scan>
代码通过读取xml获取bean
ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("SpringBean.xml");
TestCollection test=applicationContext.getBean("test",TestCollection.class);
- JavaConfig配置主要用于第三方工具类的bean初始化
- 创建javaConfig类的关键在于为其添加@Configuration注解,这个注解表明它是一个配置类,该类包含在spring应用上下文中如何创建bean的细节
在config类中配置Bean
在Configuration注解中配置的bean主要是第三方工具类的初始化,步骤一般是new一个新的实例,然后通过set方法设置参数,然后返回该实例对象。
@Bean // 实际使用的redisTemplate,可以直接注入到代码中,直接操作redis
public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
RedisSerializer<?> stringSerializer = new StringRedisSerializer();
redisTemplate.setKeySerializer(stringSerializer);
redisTemplate.setValueSerializer(stringSerializer);
redisTemplate.setHashKeySerializer(stringSerializer);
redisTemplate.setHashValueSerializer(stringSerializer);
redisTemplate.setDefaultSerializer(stringSerializer);
redisTemplate.setConnectionFactory(lettuceConnectionFactory);
return redisTemplate;
}
JavaConfig注解说明
Import注解的作用就是把多个配置组合在一起,然后通过ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class)配置类读取bean的时候,统一从一个配置类里面获取
- Import注解
- @Import(要导入到容器中的组件);容器中就会自动注册这个组件,id默认是全类名
- ImportResource注解
- ImportResource和@Value进行资源文件读取
- PropertySource 注解
- Spring框架提供了PropertySource注解,目的是加载指定的属性文件
- Profile注解
- @profile注解是spring提供的一个用来标明当前运行环境的注解
@Configuration、@Bean、@DependsOn、@Primary、@Lazy、@Import、@ImportResource、@Value
配置Bean
- 注解解析
@Component 是通用标注
@Controller 标注 web 控制器
@Service 标注 Servicec 层的服务
@Respository 标注 DAO 层的数据访问
- 注解配置Bean
- 使用注解配置bean时候,并没有指定bean的id,那么Spring帮我们创建 bean时候会给一个默认的id,id为类名首字母小写
- 当类的名字是以两个或以上的大写字母开头的话,bean的名字会与类名保持一致
@Service("beanFactory")
public class BeanFactroyImpl implements BeanFactory {
@Autowired
private UserRepository userRepository;
}
@Component
public class LogonService {}
自动装载
- @Autowired
@Autowired默认是按照byType进行注入的,但是当byType方式找到了多个符合的bean,又是怎么处理的?如果发现找到多个bean,则又按照byName方式比对(默认是该类的类名,且首字母是小写),如果还有多个,则报出异常
- @Qualifier
如果容器中有一个以上匹配的Bean,则可以通过@Qualifier注解限定Bean的名称.@Qualifier("bmwCar")
- @Resource
(这个注解属于J2EE的),默认按照名称进行装配,名称可以通过name属性进行指定,如果没有指定name属性,当注解写在字段上时,默认取字段名进行安装名称查找,如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。
* @Import注解,将两个配置类组合在一起,组成一个新的配置类
@Configuration
@Import({CDConfig.class,CDPlayerConfig.class})
public class SoundSystemConfig {
}
-
@ImportSource注解,将配置文件和XML共同的加载到Spring文件中
@Configuration @ComponentScan @Import(CDConfig.class) @ImportResource("classpath:applicationContext.xml") public class CDPlayerConfig { @Bean public CDPlayer compactDisc(CompactDisc compactDisc){ return new CDPlayer(compactDisc); } }
-
XML 中引入JavaConfig
<?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:c="http://www.springframework.org/schema/c" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- spring配置文件中<beans>的子元素<bean>,每个子元素定义一个Bean,并描述了Bean该如何被装配到Spring容器中。 --> <!-- 加载CDConfig配置文件,获取一个光盘对象实例 --> <bean class="soundsystem.CDConfig" /> <bean id="cdPlayer" class="soundsystem.CDPlayer" c:cd-ref="compactDisc" /> </beans>