Java学习笔记02 ── Spring(IOC 下)

本文深入探讨了Spring框架的关键概念,包括bean的作用域、生命周期、后置处理器、引用外部属性文件、自动装配等,详细解释了如何在XML和注解方式下配置和使用这些特性。

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;


今天的内容到此结束,谢谢大家的观看,如有错误请指正,谢谢!优快云记录成长!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值