spring注解开发
前言
Spring中用于管理bean的注解分为四大类:
- 用于创建对象
- 用于给对象中的属性注入值
- 用于改变作用范围
- 用于定义生命周期
使用注解需要导入 spring-aop-5.2.6.RELEASE.jar
相关文件链接:spring5.2.6jar包等
相关面试题
@Component、@Controller、@Service、@Repository有何区别?
@Autowired和@Resource的区别?
什么是基于注解的容器配置?
前期准备
编写业务层接口 UserService、业务层实现类 UserServiceImpl
/**
* @Author: Ron
* @Create: 2020 9:37
*/
public interface UserService {
public void save();
}
/**
* @Author: Ron
* @Create: 2020 9:38
*/
public class UserServiceImpl implements UserService {
private String msg;
@Override
public void save() {
System.out.println("业务层保存成功。。。。" + msg);
}
}
编写持久层接口 UserDao、持久层实现类 UserDaoImpl
/**
* @Author: Ron
* @Create: 2020 17:31
*/
public interface UserDao {
void insert();
}
/**
* @Author: Ron
* @Create: 2020 17:32
*/
public class UserDaoImpl implements UserDao {
@Override
public void insert() {
System.out.println("持久层初始化。。。UserDaoImpl");
}
}
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.xsd">
<!-- 开启注解扫描,base-package:指定扫描的包,会扫描该包及其子子孙孙包下的所有类 -->
<context:component-scan base-package="com.test.spring5"></context:component-scan>
</beans>
1.管理bean的四类注解
1.1.用于创建bean对象
用于创建对象的有四个:@Component、@Controller、@Service、@Repository
1.1.1.@Component
作用: 把资源让spring来管理。相当于在xml中配置一个bean。
属性: value:指定bean的id。如果不指定value属性,默认bean的id是当前类的类名,首字母小写。
@Test
public void test004() {
// 1加载spring配置文件
ApplicationContext context =
new ClassPathXmlApplicationContext("service.xml");
// 2获取bean对象
UserService userService = context.getBean("userService", UserServiceImpl.class);
userService.save();
}
解决方案:
测试成功
1.1.2.@Controller @Service @Repository
@Controller:一般用于表现层实现类的注解。
@Service:一般用于业务层实现类的注解。
@Repository:一般用于持久层实现类的注解。
面试题:@Component、@Controller、@Service、@Repository有何区别?
@Component、@Controller、@Service、@Repository有何区别:
@Controller、@Service、@Repository三个注解都是针对@Component的衍生注解,他们的作用及属性都是一模一样的。
他们只不过是提供了更加明确的语义化。让标注类本身的用途更加清晰
1.2.用于给对象中的属性注入值
用于注入数据的注解有:@Value、@Autowired、@Qualifier、@Resource
相当于 property name="" value=""
1.2.1.@Value
@Value(value=“xxxx”)
作用: 注入 基本数据类型 和 String类型 数据的
value: 用于指定值
UserServiceImpl没有set方法
1.2.2.@Autowired
自动 按照类型注入。当使用注解注入属性时,set方法可以省略。它 只能注入其他bean类型 。当有多个类型匹配时,使用要注入的对象变量名称作为bean的id,在spring容器查找,找到了也可以注入成功。找不到就报错。
测试
新增 UserDaoImpl2 实现 UserDao 接口
/**
* @Author: Ron
* @Create: 2020 17:32
*/
@Repository
public class UserDaoImpl2 implements UserDao {
@Override
public void insert() {
System.out.println("持久层初始化。。。UserDaoImpl2");
}
}
怎么解决?两种方案:
-
把其中一个实现类的bean Id设置为userDao,或者把属性名改成userDaoImpl或者userDaoImpl2
-
使用@Qualifier注解
1.2.3.@Qualifier
在自动按照类型注入的基础之上,再按照Bean的id注入。它在给字段注入时不能独立使用,必须和@Autowire一起使用;但是给方法参数注入时,可以独立使用。
测试成功
1.2.4.@Resource
Spring提供了对JSR-250中@Resource注解的支持。
@Resource的装配顺序:
1、@Resource后面没有任何内容,默认通过name属性去匹配bean,找不到再按type去匹配
2、指定了name或者type则根据指定的类型去匹配bean
3、指定了name和type则根据指定的name和type去匹配bean,任何一个不匹配都将报错
也可以指定使用byType
面试题:@Autowired和@Resource的区别?
@Autowired和@Resource两个注解的区别:
@Autowired 默认按照byType方式进行bean匹配,@Resource 默认按照byName方式进行bean匹配
@Autowired 是Spring的注解,@Resource 是J2EE的注解,这个看一下导入注解的时候这两个注解的包名就一清二楚了
Spring属于第三方的,J2EE是Java自己的东西,因此,建议使用@Resource注解,以减少代码和Spring之间的耦合
1.3.用于改变作用Bean作用域范围
Scope | Description |
---|---|
singleton | (默认值)每个 Spring IoC 容器将单个 bean 定义范围限制到单个对象实例。 |
prototype | 将单个 bean 定义的作用域限定为任意数量的对象实例。 |
request | 将单个 bean 定义的范围限定为单个 HTTP 请求的生命周期;也就是说,每个 HTTP 请求都有一个自己的 bean 实例,它是在单个 bean 定义的后面创建的。仅在可感知网络的 Spring ApplicationContext 中有效。 |
session | 将单个 bean 定义的范围限定为 HTTP Session 的生命周期。仅在可感知网络的 Spring ApplicationContext 上下文中有效。 |
application | 将单个 bean 定义的范围限定为 ServletContext 的生命周期。仅在可感知网络的 Spring ApplicationContext 上下文中有效。 |
websocket | 将单个 bean 定义的范围限定为 WebSocket 的生命周期。仅在可感知网络的 Spring ApplicationContext 上下文中有效。 |
1.4.用于定义生命周期
相当于:
@PostConstruct 加在方法上,指定bean对象创建好之后,调用该方法初始化对象,类似于xml的init-method方法。
@PreDestory 加在方法上,指定bean销毁之前,调用该方法,类似于xml的destory-method方法。
修改 UserServiceImpl 代码和 测试方法
/**
* @Author: Ron
* @Create: 2020 9:38
*/
@Component
public class UserServiceImpl implements UserService {
@Value("哈哈哈,干饭人")
private String msg;
//@Autowired(required=false) //注入对象类型,按照类型注入;如果有多个,则根据属性名注入
//@Qualifier("userDaoImpl2") // 结合@Autowired注解使用,当有多个Bean的类型符合要求时,指定注入bean的id
//@Resource(name="userDaoImpl") // 按照id注入对象类型,name指定bean的id
@Resource(type=UserDaoImpl.class)
private UserDao userDao;
@Override
public void save() {
this.userDao.insert();
System.out.println("业务层保存成功。。。。" + msg);
}
@PostConstruct
public void init(){
System.out.println("执行了init方法。。。。");
}
@PreDestroy
public void destroy(){
System.out.println("执行了Destroy方法。。。。");
}
}
注意:要使 destroy() 能正常执行,UserServiceImpl必须是 单例 的,并且 容器必须关闭
测试方法(ApplicationContext没有提供容器关闭方法,使用AbstractApplicationContext创建IoC容器)
@Test
public void test004() {
// 1加载spring配置文件
// ApplicationContext更换为AbstractApplicationContext
// AbstractApplicationContext有close()f方法,可手动关闭容器
AbstractApplicationContext context =
new ClassPathXmlApplicationContext("service.xml");
// 2获取bean对象
UserService userService = context.getBean("userServiceImpl", UserServiceImpl.class);
userService.save();
context.close();
}
2.XML和注解的比较
注解的优势:
配置简单,维护方便。(我们找到了类,就相当于找到了配置)
XML的优势:
修改时,不用改源码。不涉及重新编译和部署。
Xml和注解的比较:
3.例:注解和XML
将注解的实例改为使用XML配置文件
第一步,在 UserServiceImpl 中新增 set() 方法
第二步,在xml中关闭注解扫描,创建相关bean对象,并进行数据注入
<!-- 开启注解扫描,base-package:指定扫描的包,会扫描该包及其子子孙孙包下的所有类 -->
<!-- <context:component-scan base-package="com.test.spring5"></context:component-scan>-->
<!--创建bean对象 init-method相关于@PostConstruct destroy-method相当于@PreDestroy-->
<bean id="userServiceImpl" class="com.test.spring5.service.impl.UserServiceImpl" init-method="init" destroy-method="destroy">
<!--属性注入-->
<property name="msg" value="嘻嘻嘻,打工人"></property>
<!--ref 引用注入-->
<property name="userDao" ref="userDaoImpl"></property>
</bean>
<bean id="userDaoImpl" class="com.test.spring5.dao.UserDaoImpl"></bean>
<bean id="userDaoImpl2" class="com.test.spring5.dao.UserDaoImpl2"></bean>
第三步,测试
4.完全注解开发
(1) 创建配置类 SpringConfig,替代 xml 配置文件
/**
* @Author: Ron
* @Create: 2020 8:47
*/
@Configuration
@ComponentScan(basePackages = {"com.test.spring5"})
public class SpringConfig {
}
(2) 编写测试方法
@Test
public void testService() {
// 1加载配置类
ApplicationContext context
= new AnnotationConfigApplicationContext(SpringConfig.class);
// 2获取bean对象
UserService userService = context.getBean("userServiceImpl", UserServiceImpl.class);
userService.save();
}
测试结果