往期文章:
Spring 学习总结笔记【一、快速入门】
Spring 学习总结笔记【二、IoC-控制反转】
Spring是轻代码而重配置的框架,配置比较繁重,影响开发效率,所以注解开发是一种趋势,注解代替xm配置文件可以简化配置,提高开发效率。
Spring注解方式减少了配置文件内容,更加便于管理,并且使用注解可以大大提高了开发效率!
注解本身是没有功能的,和xml一样,注解和xml都是一种元数据,元数据即解释数据的数据,也就是所谓的配置。
- xml用来管理bean;
- 注解只负责完成属性的注入;
Spring原始注解主要是替代
的配置
注解 | 说明 |
---|---|
@Component | 使用在类 上用于实例化Bean |
@Controller | 使用在web层类 上实例化Bean |
@Service | 使用在service层类 上用于实例化Bean |
@Repository | 使用在dao层类 上用于实例化Bean |
@Value | 注入普通属性 |
@Scope | 标注Bean的作用范围 |
@Authowired | 使用在字段上用于根据类型 依赖注入 |
@Qualifier | 结合@Authowired一起用于使用用于根据名称 进行依赖注入 |
@Resource | 相当于@Authowired + @Qualifier,按照名称 进行注入 |
@PostConstruct | 使用在方法中标注该方法是Bean的初始化 方法 |
@PreDestroy | 使用在方法中标注该方法是Bean的销毁 方法 |
从 Spring 2.5 开始就可以使用注解来配置依赖注入。而不是采用 XML 来描述一个 bean ,可以使用相关类,属性声明的注解,将 bean 配置移动到组件类本身,这样可以减少大量配置。当然我们需要完成两个前提条件,使用注解开发时,需要在Spring核心配置文件中配置组件扫描
,作用是指定哪个包及其其子包下的Bean需要进行扫描以便识别使用注解配置的类、字段和方法
<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.xsd">
wesd
<context:annotation-config/>
<context:component-scan base-package="com.tyt"/>
beans>
可使用注解@Component
,@Scope
,@Value
处理属性的注入。
@Component("bookDao")
@Scope("prototype")
public class BookDaoImpl implements BookDao {
@Value("tyt")
private String name;
}
相当于配置文件中的以下代码:
<bean id="bookDao" class="com.tyt.dao.impl.BookDaoImpl">bean>
相当于配置文件中的以下代码:
<bean id="bookDao" class="com.tyt.dao.impl.BookDaoImpl" scope="prototype">bean>
相当于配置文件中的以下代码:
<property name="name" value="tyt">property>
@Component有三个衍生注解,它们的作用同Component时一样的,不同的命名只不过为了区分不同的层,为了更好的进行分层,Spring可以使用其它三个注解,目前使用哪一个功能都一样。
@Controller
:Controller层,也就是控制层,接口请求的入口@Service
:service层,业务逻辑层,具体的业务逻辑实现层@Repository
:dao层,持久化层,和数据库交互的层
在Spring 学习总结笔记【一、快速入门】谈到过Spring是如何通过自动装备将依赖自动进行装配的,具体实现细节是byName
和byType
,这里的自动装配注解也是为自动装配服务的。
Spring将依赖自动进行装配,具体实现细节是byName和byType,这里的自动装配注解也是为自动装配服务的。
@Autowired是按类型byType自动转配的,不支持id也就是byName匹配:
@Service("bookService")
public class BookServiceImpl implements BookService {
// 自动装配
@Autowired
private BookDao bookDao;
}
相当于配置文件中的以下代码:
<bean id="bookService" class="com.tyt.service.impl.BookServiceImpl" autowire="byType">bean>
@Autowired
是根据类型自动装配的,加上@Qualifier
则可以根据byName
的方式自动装配,@Qualifier不能单独使用
,必须结合@Autowired
一起使用。
在使用@Qualifier之前,仅使用@Autowired,如果有两个类型一样的:
<bean id="bookDao" class="com.tyt.dao.impl.BookDaoImpl"/>
<bean id="bookDao222" class="com.tytdao.impl.BookDaoImpl"/>
那么会报类型发现多个的错误:NoUniqueBeanDefinitionException
配置上@Qualifier 注解后,也可以使用多个相同类型了,每次可以指定一个使用:
@Service("bookService")
public class BookServiceImpl implements BookService {
// 自动装配
@Autowired
@Qualifier(value="bookDao")
private BookDao bookDao;
}
相当于配置文件中的以下代码:
<bean id="bookService" class="com.tyt.service.impl.BookServiceImpl" autowire="byType">
<property name="bookDao" ref="bookDao" />
bean>
@Resource 相当于 @Qualifier + @Autowired
@Resource
- 如指定了
name
属性,则先按该属性进行byName方式进行装配;- 如果没有指定
name
属性 ①如果注解写在字段
上,默认取字段名
进行装配 ②如果注解写在setter方法
上,默认取属性名
进行装配- 如果以上都不成功,则按byType的方式自动装配
- 都不成功,则报异常。
@Service("bookService")
public class BookServiceImpl implements BookService {
@Resource("bookDao")
private BookDao bookDao;
}
@Autowired
默认按类型装配,默认情况下必须要求依赖对象存在,如果要允许null值,可以设置它的required
属性为false
。如果想使用名称装配可以结合@Qualifier注解进行使用@Qualifier
接口可以有多个实现类,可以按实现类的类名进行注入@Resource
接口可以有多个实现类,先通过byName方式进行匹配,若匹配失败再通过byType方式注入
@PostConstruct
:标注该方法是Bean的初始化方法@PreDestroy
:标注该方法是Bean的销毁方法
@Repository("bookDao")
@Scope("prototype")
public class BookDaoImpl implements BookDao {
@Value("tyt")
private String name;
// 初始化方法
@PostConstruct
public void init(){
System.out.println("init----");
}
// 销毁方法
@PreDestroy
public void destroy(){
System.out.println("destroy----");
}
}
相当于配置文件中的以下代码:
<bean id="bookDao" class="com.tyt.Dao.impl.BookDaoImpl" init-method="init" destroy-method="destroy">
<property name="name" ref="tyt" />
bean>
使用上诉原始注解还不能够完全替代xml配置文件,还需要使用注解替代的配置如下:
- 非自定义的Bean的配置:
- 加载properties文件的配置:
- 组件扫描的配置:
- 引入其他文件:
Spring新注解如下:
注解 | 说明 |
---|---|
@Configuration | 用于指定当前类是一个Spring配置类 ,当创建容器时会从该类上加载注解 |
@ComponentScan | 用于指定Spring在初始化容器时要扫描 的包。作用同在Spring核心配置文件中的 相同 |
@Import | 用于导入其他配置类 |
@Bean | 使用在方法 上,标注将该方法的返回值存储到Spring容器中 |
@PropertySource | 用于加载.properties 文件中的配置信息 |
新注解的出现又为Spring的开发方式(基于xml配置方式,注解开发)增加了一项基于Java类进行配置开发,不需要任何xml配置文件,事实上,Config类代替了xml配置文件。
标志当前类是Spring
的核心配置类
指定Spring在初始化容器时要
扫描
的包
用于导入其他
配置类
使用在
方法
上,标注将该方法的返回值存储到Spring容器中
用于加载
.properties
文件中的配置信息
① 首先定义一个 Jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test?characterEncoding=utf8
jdbc.username=root
jdbc.password=****
② 定义一个JdbcConfig类
@PropertySource("jdbc.properties")
public class JdbcConfig {
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.name}")
private String name;
@Value("${jdbc.password}")
private String password;
// 定义一个方法获得要管理的对象
// 添加 Bean, 表示当前方法返回值为一个 Bean
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName(driver);
ds.setUrl(url);
ds.setUsername(name);
ds.setPassword(password);
return ds;
}
}
相当于配置文件(命名为JdbcConfig.xml)中的以下代码:
<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.xsd">
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
bean>
beans>
③ 定义SpringConfig类
@Configuration
@ComponentScan({"com.tyt.dao", "com.tyt.service"})
@Import({JdbcConfig.class})
public class SpringConfig {
/*
* 第三方 bean 管理, 如 数据库连接池,也可将其写入其他配置类,使用@Import加载即可
* */
}
相当于配置文件(命名为SpringConfig.xml)中的以下代码:
<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.xsd">
<context:annotation-config/>
<context:component-scan base-package="com.tyt.dao"/>
<context:component-scan base-package="com.tyt.service"/>
<import resource="JdbcConfig.xml"/>
beans>
④ 使用Spring的API获取Bean的实例
public static void main(String[] args) {
ApplicationContext app = new AnnotationConfigApplicationContext(SpringConfig.class);
BookDao bookDao = app.getBean("bookDao", BookDao.class);
bookDao.save();
BookService bookService = app.getBean("bookService", BookService.class);
bookService.save();
DataSource dataSource = app.getBean(DataSource.class);
System.out.println(dataSource);
}
总结
到这篇为止,终于全面了解了基于元数据的IOC注入模式:XML配置、注解模式、Java配置类,这几种都可以混合使用,在合适的场景使用合适的元数据注入模式,XML比较清晰,注解模式比较快捷,Java配置类模式完全不依赖配置文件,只能说各有特色。
下期文章:
Spring 学习总结笔记【四、整合Junit】