Spring 基础注解(2.x)
笔记目录: 《孙哥说Spring5》学习笔记
注解基础概念
什么是注解编程?
- 在 类 或者 方法 上加入特定的注解(
@xxx
),完成特定功能的开发
@Component
public class XXX{}
为什么要学习注解编程?
- 注解开发方便,代码简单,开发速度大大提高
- 注解开发是 Spring 开发潮流
Spring 2.x 引入注解,Spring 3.x 完善注解,SpringBoot 普及、推广注解编程
注解的作用
替换 XML 这种配置形式,简化配置。
替换接口,实现调用双方的契约性。
- 通过注解的方式,在功能调用者和功能提供者之间达成契约,进而进行功能的调用。因为注解的应用的更为方便灵活,所以在现在的开发中,更推荐通过注解的方式完成。
Spring 注解的发展历程
- Spring 2.x: 开始支持注解编程
@Component
、@Service
、@Scope
…
目的:提供的这些注解只是为了某些 XML 的配置,作为 XML 开发的有益补充。 - Spring 3.x:
@Configuration
、@Bean
…
目的:彻底替换 XML,基于纯注解 - Spring 4.x: SpringBoot 提倡使用注解进行开发
Spring 基于注解进行配置后,还能否解耦合呢?
- 在 Spring 框架应用注解时,如果对注解配置的内容不满意,可以通过 Spring 配置文件覆盖。
对象创建相关注解
搭建开发环境:让Spring框架在设置包及其子包中扫描对应的注解,使其生效。
<context:component-scan base-package="com.yusael"/>>
@Component
作用:替换原有Spring配置文件中的 <bean>
标签
id
属性:在@Component
中提供了默认的设置方式:首单词首字母小写(UserDAO --> userDAO)class
属性:通过反射获得的class
的内容
@Component
细节:
- 如何显式指定工厂创建对象的 id 值
@Component("u")
- Spring 配置文件可以覆盖注解配置内容(相同的
id
和class
)
applicationContext.xml
<bean id="user" class="com.yusael.bean.User">
<property name="id" value="10"/>
</bean>
id值、class值 要和 注解 中配置的一样才会覆盖,
否则 Spring 会创建新的对象。
@Repository、@Service、@Contoller
@Repository
、@Service
、@Controller
都是 @Component
的 衍生注解。
本质上这些衍生注解就是 @Component
,通过源码可以看见他们都使用了 @Component
;
它们的存在是为了:更加准确的表达一个类型的作用。
@Repository
public class UserDAO {}
@Service
public class UserService {}
@Controller
public class UserController {}
注意:Spring 整合 Mybatis 开发过程中,不使用 @Repository
、@Component
@Scope:控制对象创建次数
作用:控制简单对象创建次数
注意:不添加 @Scope
,Spring 提供默认值 singleton
XML 配置:
<bean id="customer" class="com.yusael.Customer" scope="singleton | prototype"/>
注解:
// 创建单例对象
@Component
@Scope("singleton")
public class Customer {}
// 创建多例对象
@Component
@Scope("prototype")
public class Customer {}
@Lazy:延迟创建单实例对象
作用:延迟创建单实例对象
注意:一旦使用 @Lazy
注解后,Spring 会在使用这个对象的时候,才创建这个对象。
XML 配置:
<bean id="account" class="com.yusael.Account" lazy="true"/>
注解:
@Component
@Lazy
public class Account {
public Account() {
System.out.println("Account.Account");
}
}
@PostConstruct、@PreDestroy:生命周期注解
初始化相关方法: @PostConstruct
InitializingBean
<bean init-method=""/>
销毁方法:@PreDestory
DisposableBean
<bean destory-method=""/>
注意:
- 上述的两个注解并不是 Spring 提供的,由 JSR(JavaEE规范)520 提供
- 再次验证,通过注解实现了接口的契约性
注入相关注解
用户自定义类型 @Autowired
@Autowired
注解 基于类型进行注入 [推荐]:
- 注入对象的类型,必须与目标成员变量类型相同或者是其子类(实现类)
@Autowired
private UserDAO userDAO;
@Autowired
、@Qualifier
注解联合实现 基于名字进行注入 [了解]
- 注入对象的 id 值,必须与
@Qualifier
注解中设置的名字相同
@Autowired
@Qualifier("userDAOImpl")
private UserDAO userDAO;
@Autowired
注解放置位置:
- 放置在对应成员变量的 set 方法上,调用 set 方法赋值(在 set 里写的代码会被执行)
- 直接放置在成员变量上,Spring 通过反射直接对成员变量进行赋值 [推荐]
JavaEE 规范中类似功能的注解:
- JSR250 提供的
@Resource(name="xxx")
基于名字进行注入
等价于@Autowired
与@Qualifier
联合实现的效果
注意:@Resource
注解如果名字没有配对成功,会继续 按照类型进行注入
@Resource(name="userDAOImpl")
private UserDAO userDAO;
- JSR330 提供的
@Injection
作用与@Autowired
完全一样,一般用在 EJB3.0 中
JDK 类型 @value、@PropertySource
方法一:@value
注解的基本使用:
1. 设置xxx.properties
id = 10
name = suns
2. Spring的工厂读取这个配置文件
<context:property-placeholder location=""/>
3. 代码中进行注入
属性 @Value("${key}")
方法二:使用 @PropertySource
取代 xml配置:
1. 设置xxx.properties
id = 10
name = suns
2. 在实体类上应用@PropertySource("classpath:/xx.properties")
3. 代码
属性 @Value("${key}")
@value
注解使用细节:
@Value
注解不能应用在静态成员变量上,如果使用,获取的值为 null@Value
注解 + Properties 这种方式,不能注入集合类型
Spring 提供新的配置形式 YAML(YML) (更多的用于SpringBoot中)
注解扫描 - component-scan
这样配置,会扫描当前包及其子包 :
<context:component-scan base-package="com.yusael"/>
排除方式:设置不扫描哪些注解
<context:component-scan base-package="com.yusael">
<context:exclude-filter type="" expression=""/>
</context:component-scan>
type="xxx"
,xxx
有以下几个可选项:
assignable
:排除特定的类型annotation
:排除特定的注解aspectj
:切入点表达式,比较常用
包切入点:com.yusael.bean..*
类切入点:*..User
regex
:正则表达式,不常用,与切入点类似custom
:自定义排除策略,常用于框架底层开发(在 SpringBoot 源码中大量使用)
排除策略可以叠加使用:
<context:component-scan base-package="com.yusael">
<context:exclude-filter type="assignable" expression="com.yusael.bean.User"/>
<context:exclude-filter type="aspectj" expression="com.yusael.injection..*"/>
</context:component-scan>
包含方式:设置扫描哪些注解
<context:component-scan base-package="com.yusael" use-default-filters="false">
<context:include-filter type="" expression=""/>
</context:component-scan>
与排除方式使用的区别:
use-default-filters="false"
让 Spring 默认的注解扫描方式失效<context:include-filter type="" expression=""/>
用于指定扫描哪些注解
type="xxx"
与排除方式完全一样,可以参考上面
包含策略也可以叠加使用:
<context:component-scan base-package="com.baizhiedu" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
</context:component-scan>
对于注解开发的思考
注解与xml配置互通
Spring 通过注解配置,与通过xml文件进行配置是互通的。
// 通过注解配置UserDAOImpl
@Repository
public class UserDAOImpl{
}
public class UserServiceImpl{
private UserDAO userDAO;
set
get
}
// 通过xml配置创建userDAO对象
<bean id="userService" class="com.baizhiedu.UserServiceImpl">
<property name="userDAO" ref="userDAOImpl"/>
</bean>
什么情况下使用注解,什么情况下使用配置文件
基础注解(@Component
、@Autowired
、@Value
)用于程序员开发类型的配置:
-
在程序员开发的类型上,可以加入对应注解进行对象的创建
User、UserService、UserDAO、UserAction… 这些类都很适合用注解 -
应用其他非程序员开发的类型时(框架自带的类),需要使用
<bean>
标签进行配置
SqlSessionFactoryBean、MapperScannerConfigure 等 Spring 创建的类,无法使用注解