bean的作用域
Spring中,<bean标签有一个scope属性,可以用来设置 bean的作用域。scope属性有四个取值,分别是:

singleton产生的bean是单例的,prototype(原型)产生的bean是每调用一次产生一个新的。其中singleton所产生的bean是在IOC容器创建的时候就创建,prototype产生的bean是调用的时候才会创建。
bean的生命周期
Spring产生的bean的生命周期有五个阶段:
- 通过构造器或者工厂方法来创建bean
- 为bean的属相赋值、依赖注入
- 调用bean的初始化方法
- 使用bean
- 调用销毁方法销毁bean
下面我们来验证一下:
1.创建一个Person类,有id、name两个属性,然后在空参构造器中输出“1.Person构造器被调用”,在setId方法中输出“2.依赖注入”,然后再创建init()和destroy()方法分别输出“3.初数化方法”、“4.销毁方法”。
public class Person {
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
System.out.println("2.依赖注入");
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person [id=" + id + ", name=" + name + "]";
}
public Person() {
super();
System.out.println("1.Person构造器被调用");
}
public void init() {
System.out.println("3.初始化方法");
}
public void destory() {
System.out.println("5.销毁方法");
}
}
2.在xml文件中配置bean,在bean标签中有init-method、destroy-method两个属性用来指定初始化方法和销毁方法
<bean id="p1" class="com.glq.ioc.test.Person" scope="singleton" init-method="init" destroy-method="destory">
<property name="id" value="10001"></property>
<property name="name" value="lxy"></property>
</bean>
3.然后创建测试类,获取该对象打印输出,最后关闭容器。代码和执行结果如下:
public class Test {
public static void main(String[] args) {
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("person.xml");
Person bean0 = ac.getBean("p1",Person.class);
System.out.println("4.使用bean"+bean0);
ac.close();
}
}

bean的后置处理器
就是在bean的初始化前后进行对bean的额外处理,有在初始化之前和在初始化之后两种处理。该处理器会对Spring管理的所有的bean都进行处理。
使用步骤:
1.创建一个类,继承BeanpostProncessor接口
2.重写postProcessBeforeInitialization()、postProcessAfterInitialization()两个方法
3.在xml中配置改类
①、②:创建一个AfterBean类 继承BeanpostProncessor接口并实现方法
public class AfterBean implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("初始化之前");
Person person = (Person) bean;
if(person.getId().equals("1001")) {
person.setName("张无忌");
}else {
person.setName("赵敏");
}
return person;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
// TODO Auto-generated method stub
return bean;
}
}
③:在xml文件中进行配置:
<bean class="com.glq.ioc.test.AfterBean"></bean>
执行结果:

引用外部属性文件
Spring中可以引用外部的配置文件来获取值,这里以获取数据库连接为例讲解。
1.首先创建一个db.properties文件,用来存储;连接数据库所用到的信息。
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=root
jdbc.password=root
2.xml中引入context命名空间
3.使用<context:property-placeholder 标签加载配置文件,有一个location属性来填写配置文件名
<context:property-placeholder location="db.properties"/>
4.使用${}的方式来获取值
<bean id="database" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
5.创建测试类,获取数据库连接
public class Test {
public static void main(String[] args) throws SQLException {
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("person.xml");
Person bean0 = ac.getBean("p1",Person.class);
System.out.println("4.使用bean"+bean0);
DruidDataSource bean = ac.getBean("database",DruidDataSource.class);
System.out.println(bean.getConnection());
ac.close();
}
}
执行结果:

基于XML的自动装配
针对于bean的非字面量属性,Spring提供了自动装配机制。这里主要介绍根据类型和根据名称装配。
1.首先创建UserDao、Service、Servlet三个类,Service中有一个属性是UserDao类型的、Servlet中有一个属性是Service类型的。
userDao:
public class UserDao {
public void saveUser() {
System.out.println("dao层进行保存");
}
}
service:
public class Service {
private UserDao userDao;
public void saveUser() {
userDao.saveUser();
}
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public Service() {
super();
}
}
servlet:
public class Servlet {
private Service service;
public void saveUser() {
service.saveUser();
}
public Servlet() {
super();
}
public Service getService() {
return service;
}
public void setService(Service service) {
this.service = service;
}
}
2.创建xml文件,首先引入UserDao类型的bean
<bean id="userDao" class="com.glq.ioc.auto.UserDao"></bean>
然后要引入Service类型的bean,有一个UserDao类型的属性而且我们已经配置好了一个UserDao类型的bean,可以使用自动装配。
在《bean标签中有一个autowire属性,代表自动装配,我们这里使用byType即根据类型来装配
<bean id="service" class="com.glq.ioc.auto.Service" autowire="byType"></bean>
最后要引入Servlet类型的bean,这里我们使用byName即根据名称来装配。根据名称装配要求属性名和id要一致,刚好有一致的bean可以赋值。
<bean class="com.glq.ioc.auto.Servlet" autowire="byName"></bean>
3.创建Test类,获取Servlet对象然后进行执行saveUser()方法。执行结果并不会报错而且正常输出”dao层进行保存“。
public class Test {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("auto.xml");
Servlet bean = ac.getBean(Servlet.class);
bean.saveUser();
}
}
关于自动装配的一些说明:
1.只能装配非字面量属性
2.byName要求bean中的id和属性名要一致,只有一致才能赋值成功
3.byType是兼容性赋值,即子类父类都可以进行赋值,要求spring容器中只能有一个bean能为属性赋值
4.基于xml的自动装配会将所有字面量属性都进行赋值,所以一般不采用这种方式
基于注解的自动装配
基于xml的自动装配有弊端,一般我们会使用如下的基于注解的自动装配。
①:使用注解表示组件(bean)
在Spring中有四种注解来标识组件,分别是:
- @component:标识一个普通的bean
- @Repository:一个持久化层的组件
- @Service:一个业务逻辑层的组件
- @Controller:一个控制层的组件
这四种类型其实功能是一样的,只不过是为了能够更清楚的了解到该类是哪一层的类。使用这些注解生成的bean的id默认是以类名首字母小写命名的。注解中可以写一个value来设置生成的id,例如:@Controller(value=“id”)
②:在需要自动装配的属性上加上@Autowired注解,表明需要自动装配。
③:在xml文件中设置扫描组件
使用<context:component-scan base-package=“包名”/>标签来标识要扫描的包,即在该包下并且加有相应注解的都会生成Spring中的bean。如果要扫描多个包则以逗号分隔开
设置扫描组件的时候还可以设置包含或者排除某些组件。
在<context:component-scan base-package=“包名”/>标签中使用子<context:include-filter标签来表明包含某一些组件 其中有一个type属性来表明根据什么来扫描,annotation表示根据注解类型来扫描、assignable表名根据类名(或者其子类)来进行扫描。使用<context:exclude-filter子标签来表示排除某些组件。注意包含的时候<context:component-scan标签中的use-default-filters属性要设置为false,排除的时候要设置为true;
<context:component-scan base-package="com.glq.ioc.auto" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<context:include-filter type="assignable" expression="com.glq.ioc.auto.UserDao"/>
<context:include-filter type="assignable" expression="com.glq.ioc.auto.Servlet"/>
</context:component-scan>
<context:component-scan base-package="com.glq.ioc.auto" use-default-filters="true">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<context:exclude-filter type="assignable" expression="com.glq.ioc.auto.UserDao"/>
<context:exclude-filter type="assignable" expression="com.glq.ioc.auto.Servlet"/>
</context:component-scan>
注意:
- byType装配解决不了时会自动切换成byName,此时要求spring容器中,有一个bean的id和属性名一致
- 若自动装配时,匹配到多个能够复制的bean,可使用@Qualifier(value=“beanId”)指定使用的bean
- @Autowired和@Qualifier(value=“beanId”)可以一起作用域一个带形参的方法上,此时,@Qualifier(value=“beanId”)所指定的bean作用于形参
- 一个<context:component-scan中可以出现多个include,也可以同时出现多个exclude,但是两个不能同时出现
- 可以通过@Qualifier注解,然后通过value属性来标识以某个bean名来自动装配
@Autowired
@Qualifier(value = "userDaoImpl")
private UserDAao userDAao;
本文深入探讨了Spring框架的关键概念,包括bean的作用域、生命周期、后置处理器、引用外部属性文件、自动装配等,详细解释了如何在XML和注解方式下配置和使用这些特性。
1555

被折叠的 条评论
为什么被折叠?



