学习大数据——通过注解配置bean

概述

相对于XML方式而言,通过注解的方式配置bean更加简洁和优雅,而且和MVC组件化开发的理念十分契合,是开发中常用的使用方式。

  • 实例的项目结构
    项目结构

使用注解标识组件

  1. 普通组件:@Component
    标识一个受Spring IOC容器管理的组件
  2. 持久化层组件:@Repository
    标识一个受Spring IOC容器管理的持久化层组件
  3. 业务逻辑层组件:@Service
    标识一个受Spring IOC容器管理的业务逻辑层组件
  4. 表述层控制器组件:@Controller
    标识一个受Spring IOC容器管理的表述层控制器组件
  5. 组件命名规则
    ①默认情况:使用组件的简单类名首字母小写后得到的字符串作为bean的id
    ②使用组件注解的value属性指定bean的id
    注意:事实上Spring并没有能力识别一个组件到底是不是它所标记的类型,即使将@Respository注解用在一个表述层控制器组件上面也不会产生任何错误,所以 @Respository、@Service、@Controller这几个注解仅仅是为了让开发人员自己明确当前的组件扮演的角色。
  • User:
//@Component
public class User {
}
  • UserDao:
public interface UserDao {
	void saveUser();
}

  • UserDaoImpl:
/*
 * 通过注解将当前类交给IOC容器管理之后,默认在IOC容器中对象的id是类名的首字母小写
 * 我们可以通过注解的value属性来指定该id,而且value属性名可以省略不写
 */
@Repository("userDao1")
//@Repository(value="userDao")
public class UserDaoImpl implements UserDao {

	@Override
	public void saveUser() {
		System.out.println("UserDao正在向数据库插入用户信息.....");
	}

}
  • UserDaoImpl2:
/*
 * 通过注解将当前类交给IOC容器管理之后,默认在IOC容器中对象的id是类名的首字母小写
 * 我们可以通过注解的value属性来指定该id,而且value属性名可以省略不写
 */
@Repository("userDao2")
//@Repository(value="userDao")
public class UserDaoImpl2 implements UserDao {

	@Override
	public void saveUser() {
		System.out.println("UserDao2正在向数据库插入用户信息.....");
	}

}

扫描组件

组件被上述注解标识后还需要通过Spring进行扫描才能够侦测到。

  1. 指定被扫描的package

  2. 详细说明
    ①base-package属性指定一个需要扫描的基类包,Spring容器将会扫描这个基类包及其子包中的所有类。
    ②当需要扫描多个包时可以使用逗号分隔。
    ③如果仅希望扫描特定的类而非基包下的所有类,可使用resource-pattern属性过滤特定的类,示例:
    <context:component-scan
    base-package=“com.atguigu.component”
    resource-pattern=“autowire/*.class”/>

    ④包含与排除
    ●<context:include-filter>子节点表示要包含的目标类
    注意:通常需要与use-default-filters属性配合使用才能够达到“仅包含某些 组件”这样的效果。即:通过将use-default-filters属性设置为false, 禁用默认过滤器,然后扫描的就只是include-filter中的规则指定的 组件了。
    ●<context:exclude-filter>子节点表示要排除在外的目标类
    ●component-scan下可以拥有若干个include-filter和exclude-filter子节点
    ●过滤表达式

类别 实例 说明
annotation com.atguigu.XxxAnnotation 过滤所有标注了XxxAnnotation的类。这个规则根据目标组件是否标注了指定类型的注解进行过滤。
assignable com.atguigu.BaseXxx 过滤所有BaseXxx类的子类。这个规则根据目标组件是否是指定类型的子类的方式进行过滤。
  1. JAR包依赖
    需要加入对spring-aop的依赖,但因为spring-context已经对spring-aop进行了依赖,因此不需要重复加入.
  • beans-annotation.xml:
<?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-4.0.xsd">

	<!-- 设置自扫描的包 
		base-package属性:设置一个基础包,Spring会自动扫描该包以及其他包
	-->
<!-- 	<context:component-scan base-package="com.learn.spring.annotation" resource-pattern="dao/impl/*.class"></context:component-scan> -->
	<context:component-scan base-package="com.learn.spring.annotation"></context:component-scan>
<!-- 	<context:component-scan base-package="com.learn.spring.annotation" use-default-filters="false"> -->
		
		<!--  
			字标签context:include-filter:用来设置只扫描那个包下的类
			注意:此时需要将父标签的use-default-filter属性的值设置为false
				如果type的值是annotation,那么expression的值是注解的全类名
				如果type的值是assignable,那么expression的值是接口或者实现类的全类名
		-->
<!-- 		<context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/> -->
<!-- 		<context:include-filter type="assignable" expression="com.learn.spring.annotation.dao.UserDao"/> -->
<!-- 	</context:component-scan> -->


<!-- 	<context:component-scan base-package="com.learn.spring.annotation"> -->
		
		<!--  
			字标签context:exclude-filter:用来设置不扫描那个包下的类
			注意:此时不需要将父标签的use-default-filter属性的值设置为false
				如果type的值是annotation,那么expression的值是注解的全类名
				如果type的值是assignable,那么expression的值是接口或者实现类的全类名
		-->
			<!-- 当使用org.springframework.stereotype.Component时所有注解都被排除,因为其他注解都用到了Component -->
<!-- 		<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Component"/> -->
<!-- 		<context:exclude-filter type="assignable" expression="com.learn.spring.annotation.dao.UserDao"/> -->

<!-- 	</context:component-scan> -->
</beans>

组件装配

  1. 需求
    Controller组件中往往需要用到Service组件的实例,Service组件中往往需要用到Repository组件的实例。Spring可以通过注解的方式帮我们实现属性的装配。

  2. 实现依据[了解]
    在指定要扫描的包时,<context:component-scan> 元素会自动注册一个bean的后置处 理器:AutowiredAnnotationBeanPostProcessor的实例。该后置处理器可以 自动装配标
    记了@Autowired、@Resource或@Inject注解的属性。

  3. @Autowired注解
    ①根据类型实现自动装配。
    ②构造器、普通字段(即使是非public)、一切具有参数的方法都可以应用@Autowired 注解
    ③默认情况下,所有使用@Autowired注解的属性都需要被设置。当Spring找不到匹 配的bean装配属性时,会抛出异常。
    ④若某一属性允许不被设置,可以设置@Autowired注解的required属性为 false
    ⑤默认情况下,当IOC容器里存在多个类型兼容的bean时,Spring会尝试匹配bean 的id值是否与变量名相同,如果相同则进行装配。如果bean的id值不相同,通过类 型的自动装配将无法工作。此时可以在@Qualifier注解里提供bean的名称。Spring 甚至允许在方法的形参上标注@Qualifiter注解以指定注入bean的名称。 ⑥@Autowired注解也可以应用在数组类型的属性上,此时Spring将会把所有匹配的bean进行自动装配。
    ⑦@Autowired注解也可以应用在集合属性上,此时Spring读取该集合的类型信息,然后自动装配所有与之兼容的bean。
    ⑧@Autowired注解用在java.util.Map上时,若该Map的键值为String,那么 Spring将自动装配与值类型兼容的bean作为值,并以bean的id值作为键。

  4. @Resource
    @Resource注解要求提供一个bean名称的属性,若该属性为空,则自动采用标注处的变量或方法名作为bean的名称。

  5. @Inject
    @Inject和@Autowired注解一样也是按类型注入匹配的bean,但没有reqired属性。

  • UserService:
public interface UserService {
	
	void saveUser();
}
  • UserServiceImpl:
@Service("userService")
public class UserServiceImpl implements UserService {

	/*
	 * 自动装配的规则(@Autowired)
	 * 	1.根据属性类型实现自动装配
	 * 	2.如果根据类型无法实现自动装配,会以属性名名作为id从IOC容器中寻找以实现自动装配
	 * 	3.如果通过1和2都不能实现自动装配,可以通过@Qualifier注解的value属性来指定id
	 * 		以实现自动装配,而且value属性名可以省略不写
	 */
//	@Qualifier(value="userDao2")
	@Qualifier("userDao2")
	@Autowired
	private UserDao userDao;
	
	/*
	 * 添加@Autowired注解的属性默认必须注入成功,否则会抛出异常
	 * 	我们可以通过设置该注解的required属性值为false来告诉Spring当前属性可以不装配
	 */
	@Autowired(required = false)
	private User user;
	@Override
	public void saveUser() {
		//调用UserDao中保存用户信息的方法
		userDao.saveUser();
		System.out.println(user);
	}

}
  • AnnotationTest.java:
class AnnotationTest {

	//创建IOC容器对象
	ApplicationContext ioc = new ClassPathXmlApplicationContext("beans-annotation.xml");
	
	@Test
	void testUserDao() {
//		UserDao userDao = (UserDao) ioc.getBean("userDaoImpl");
//		当直接中没有指定value时:id为类名首字母小写
		UserDao userDao = (UserDao) ioc.getBean("userDao");
		System.out.println(userDao);
	}

	@Test
	void testUserService() {
		UserService userService = (UserService) ioc.getBean("userService");
		//调用UserServic中保存用户信息的方法
		userService.saveUser();
	}
}

课件引用自尚硅谷课程,代码部分由博主纯手工完成

发布了37 篇原创文章 · 获赞 7 · 访问量 679

猜你喜欢

转载自blog.csdn.net/qq_40394792/article/details/104394522