Spring-注解编程
第一章、注解基础概念
1、什么是注解编程
指的是在类或者方法上加入特定的注解(@xxx),完成特定功能的开发
@Component
public class XXX{}
2、注解的作用
- 替换XML这种配置文件,简约配置
- 替换接⼝,实现调⽤双⽅的契约性
通过注解的⽅式,在功能调⽤者和功能提供者之间达成约定,进⽽进⾏功能的调⽤。因为注解应⽤更为⽅便灵活,所以在现在的开发中,更推荐通过注解的形式,完成
3、Spring注解的发展历程
1. Spring2.x开始⽀持注解编程 @Component @Service @Scope..
⽬的:提供的这些注解只是为了在某些情况下简化XML的配置,作为XML开发的有益补充。
2. Spring3.x @Configuration @Bean..
⽬的:彻底替换XML,基于纯注解编程
3. Spring4.x SpringBoot
提倡使⽤注解常⻅开发
4、Spring注解开发的一个问题
Spring基于注解进⾏配置后,还能否解耦合呢?
在Spring框架应⽤注解时,如果对注解配置的内容不满意,可以通过Spring配置⽂件进⾏覆盖的。
第二章、Spring的基础注解(Spring2.x)
这个阶段的注解,仅仅是简化XML的配置,并不能完全替代XML
1、对象创建相关注解
- 搭建开发环境
<context:component-scan base-package="com.xiaohe"/>
作⽤:让Spring框架在设置包及其⼦包中扫描对应的注解,使其⽣效。
-
对象创建相关注解
- @Component
作⽤:替换原有spring配置⽂件中的<bean标签 注意: id属性 component注解 提供了默认的设置⽅式 ⾸单词⾸字⺟⼩写 class属性 通过反射获得class内容
-
@Component 细节
- 如何显示指定⼯⼚创建对象的id值
@Component("u")
- Spring配置⽂件覆盖注解配置内容
applicationContext.xml <bean id="u" class="com.xiaohe.anno.User"/> id值 class的值 要和 注解中的设置保持⼀值
-
@Component的衍⽣注解
@Repository ---> XXXDAO @Repository public class UserDAO{ } @Service @Service public class UserService{ } @Controller @Controller public class RegAction{ } 注意:本质上这些衍⽣注解就是@Component 作⽤ <bean 细节 @Service("s") ⽬的:更加准确的表达⼀个类型的作⽤ 注意:Spring整合Mybatis开发过程中 不使⽤@Repository @Component
-
@Scope注解
作⽤:控制简单对象创建次数
注意:不添加@Scope Spring提供默认值 singleton
<bean id="" class="" scope="singleton|prototype"/>
- @Lazy注解
作⽤:延迟创建单实例对象
注意:⼀旦使⽤了@Lazy注解后,Spring会在使⽤这个对象时候,进⾏这个对象的创建
<bean id="" class="" lazy="false"/>
- ⽣命周期⽅法相关注解
1. 初始化相关⽅法 @PostConstruct
InitializingBean
<bean init-method=""/>
2. 销毁⽅法 @PreDestroy
DisposableBean
<bean destory-method=""/>
注意:1. 上述的2个注解并不是Spring提供的,JSR(JavaEE规范)520
2. 再⼀次的验证,通过注解实现了接⼝的契约性
2、注入相关注解
- 用户自定义类型
@Autowired细节
1. Autowired注解基于类型进⾏注⼊ [推荐]
基于类型的注⼊:注⼊对象的类型,必须与⽬标成员变量类型相同或者是其⼦类
(实现类)
2. Autowired Qualifier 基于名字进⾏注⼊ [了解]
基于名字的注⼊:注⼊对象的id值,必须与Qualifier注解中设置的名字相同
3. Autowired注解放置位置
a) 放置在对应成员变量的set⽅法上
b) 直接把这个注解放置在成员变量之上,Spring通过反射直接对成员变量进⾏
注⼊(赋值)[推荐]
4. JavaEE规范中类似功能的注解
JSR250 @Resouce(name="userDAOImpl") 基于名字进⾏注⼊
@Autowired()
@Qualifier("userDAOImpl")
注意:如果在应⽤Resource注解时,名字没有配对成功,那么他会继续
按照类型进⾏注⼊。
JSR330 @Inject 作⽤ @Autowired完全⼀致 基于类型进⾏注⼊ ---》
EJB3.0
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
-
JDK类型
@Value注解完成 1. 设置xxx.properties id = 10 name = xiaohe 2. Spring的⼯⼚读取这个配置⽂件 <context:property-placeholder location=""/> 3. 代码 属性 @Value("${key}")
- @PropertySource
1. 作⽤:⽤于替换Spring配置⽂件中的<context:property-placeholder location=""/>标签 2. 开发步骤 1. 设置xxx.properties id = 10 name = xiaohe 2. 应⽤@PropertySource 3. 代码 属性 @Value()
-
@Value注解使⽤细节
@Value注解不能应⽤在静态成员变量上
如果应⽤,赋值(注⼊)失败
@Value注解+Properties这种⽅式,不能注⼊集合类型
Spring提供新的配置形式 YAML YML (SpringBoot)
3、注解扫描详解
<!--开启注解扫描-->
<context:component-scan base-package="com.xiaohe.anno"/>
当前包 及其 ⼦包
1、排除方式
<context:component-scan base-package="com.xiaohe.anno">
<context:exclude-filter type="" expression=""/>
type:assignable:排除特定的类型 不进⾏扫描
annotation:排除特定的注解 不进⾏扫描
aspectj:切⼊点表达式
包切⼊点: com.xiaohe.bean..*
类切⼊点: *..User
regex:正则表达式
custom:⾃定义排除策略框架底层开发
</context:component-scan>
排除策略可以叠加使⽤
<context:component-scan base-package="com.xiaohe">
<context:exclude-filter type="assignable"expression="com.xiaohe.bean.User"/>
<context:exclude-filter type="aspectj"expression="com.xiaohe.injection..*"/>
</context:component-scan>
2、 包含⽅式
<context:component-scan base-package="com.xiaohe" use-defaultfilters="false">
<context:include-filter type="" expression=""/>
</context:component-scan>
1. use-default-filters="false"
作⽤:让Spring默认的注解扫描⽅式 失效。
2. <context:include-filter type="" expression=""/>
作⽤:指定扫描那些注解
type:assignable:排除特定的类型 不进⾏扫描
annotation:排除特定的注解 不进⾏扫描
aspectj:切⼊点表达式
包切⼊点: com.xiaohe.bean..*
类切⼊点: *..User
regex:正则表达式
custom:⾃定义排除策略框架底层开发
包含的⽅式⽀持叠加
<context:component-scan base-package="com.xiaohe" use-defaultfilters="false">
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Repository"/>
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Service"/>
</context:component-scan>
第三章、Spring的⾼级注解(Spring3.x 及以上)
1、配置Bean
Spring在3.x提供的新的注解,⽤于替换XML配置⽂件。
@Configuration
public class AppConfig{
}
- AnnotationConfigApplicationContext
1. 创建⼯⼚代码
ApplicationContext ctx = new AnnotationConfigApplicationContext();
2. 指定配置⽂件
1. 指定配置bean的Class
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
2. 指定配置bean所在的路径
ApplicationContext ctx = new AnnotationConfigApplicationContext("com.xiaohe");
-
配置Bean开发的细节分析
- 基于注解开发使⽤⽇志
不能集成Log4j 集成logback
-
引⼊相关jar
<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.25</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>1.7.25</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>org.logback-extensions</groupId> <artifactId>logback-ext-spring</artifactId> <version>0.1.4</version> </dependency
- 引⼊logback配置⽂件 (logback.xml)
<?xml version="1.0" encoding="UTF-8"?> <configuration> <!-- 控制台输出 --> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <!--格式化输出:%d表示⽇期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:⽇志消息,%n是换⾏符--> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS}[%thread] %-5level %logger{50} - %msg%n</pattern> </encoder> </appender> <root level="DEBUG"> <appender-ref ref="STDOUT" /> </root> </configuration>
-
@Configuration注解的本质
本质:也是@Component注解的衍⽣注解 可以应⽤<context:component-scan进⾏扫描
2、@ComponentScan注解
@ComponentScan注解在配置bean中进⾏使⽤,等同于XML配置⽂件中的
<context:component-scan>标签
⽬的:进⾏相关注解的扫描 (@Component @Value ...@Autowired)基本使⽤
1、 基本使⽤
@Configuration
@ComponentScan(basePackages = "com.xiaohe.scan")
public class AppConfig {
}
<context:component-scan base-package=""/>
2、排除、包含的使⽤
- 排除
<context:component-scan base-package="com.xiaohe">
<context:exclude-filter type="assignable" expression="com.xiaohe.bean.User"/>
</context:component-scan>
@ComponentScan(basePackages = "com.xiaohe.scan",
excludeFilters = {@ComponentScan.Filter(type=
FilterType.ANNOTATION,value={Service.class}),
@ComponentScan.Filter(type=FilterType.ASPECTJ,pattern = "*..User1")})
type = FilterType.ANNOTATION value
.ASSIGNABLE_TYPE value
.ASPECTJ pattern
.REGEX pattern
.CUSTOM value
- 包含
<context:component-scan base-package="com.xiaohe" use-defaultfilters="false">
<context:include-filter type="" expression=""/>
</context:component-scan>
@ComponentScan(basePackages = "com.xiaohe.scan",
useDefaultFilters = false,
includeFilters = {@ComponentScan.Filter(type=
FilterType.ANNOTATION,value={Service.class})})
type = FilterType.ANNOTATION value
.ASSIGNABLE_TYPE value
.ASPECTJ pattern
.REGEX pattern
.CUSTOM value
第四章、纯注解版Spring+MyBatis整合
1、基础配置 (配置Bean)
1. 连接池
<!--连接池-->
<bean id="dataSource"
class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName"value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/hezb?useSSL=false"></property>
<property name="username" value="root"></property>
<property name="password" value="123456"></property>
</bean>
@Bean
public DataSource dataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("");
dataSource.setUrl();
...
return dataSource;
}
2. SqlSessionFactoryBean
<!--创建SqlSessionFactory SqlSessionFactoryBean-->
<bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="typeAliasesPackage"value="com.xiaohe.entity"></property>
<property name="mapperLocations">
<list>
<value>classpath:com.xiaohe.mapper/*Mapper.xml</value>
</list>
</property>
</bean>
@Bean
public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
sqlSessionFactoryBean.setTypeAliasesPackage("");
...
return sqlSessionFactoryBean;
}
3. MapperScannerConfigure
<!--创建DAO对象 MapperScannerConfigure-->
<bean id="scanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="sqlSessionFactoryBeanName"value="sqlSessionFactoryBean"></property>
<property name="basePackage" value="com.xiaohe.dao">
</property>
</bean>
@MapperScan(basePackages={"com.xiaohe.dao"}) ---> 配置bean完成
- 编码
1. 实体
2. 表
3. DAO接⼝
4. Mapper⽂件
1、 MapperLocations编码时通配的写法
//设置Mapper⽂件的路径
sqlSessionFactoryBean.setMapperLocations(Resource..);
Resource resouce = new ClassPathResouce("UserDAOMapper.xml")
sqlSessionFactoryBean.setMapperLocations(new
ClassPathResource("UserDAOMapper.xml"));
<property name="mapperLocations">
<list>
<value>classpath:com.xiaohe.mapper/*Mapper.xml</value>
</list>
</property>
⼀组Mapper⽂件
ResourcePatternResolver resolver = new
PathMatchingResourcePatternResolver();
Resource[] resources =
resolver.getResources("com.xiaohe.mapper/*Mapper.xml");
sqlSessionFactoryBean.setMapperLocations(resources)
2、配置Bean数据耦合的问题
mybatis.driverClassName = com.mysql.jdbc.Driver
mybatis.url = jdbc:mysql://localhost:3306/hezb?useSSL=false
mybatis.username = root
mybatis.password = 123456
mybatis.typeAliasesPackages = com.xiaohe.mybatis
mybatis.mapperLocations = com.xiaohe.mapper/*Mapper.xml
@Component
@PropertySource("classpath:mybatis.properties")
public class MybatisProperties {
@Value("${mybatis.driverClassName}")
private String driverClassName;
@Value("${mybatis.url}")
private String url;
@Value("${mybatis.username}")
private String username;
@Value("${mybatis.password}")
private String password;
@Value("${mybatis.typeAliasesPackages}")
private String typeAliasesPackages;
@Value("${mybatis.mapperLocations}")
private String mapperLocations;
}
public class MyBatisAutoConfiguration {
@Autowired
private MybatisProperties mybatisProperties;
@Bean
public DataSource dataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(mybatisProperties.getDriverClassName());
dataSource.setUrl(mybatisProperties.getUrl());
dataSource.setUsername(mybatisProperties.getUsername());
dataSource.setPassword(mybatisProperties.getPassword());
return dataSource;
}
@Bean
public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource) {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
sqlSessionFactoryBean.setTypeAliasesPackage(mybatisProperties.getTypeAliasesPackages());
//sqlSessionFactoryBean.setMapperLocations(newClassPathResource("UserDAOMapper.xml"));
try {
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource[] resources = resolver.getResources(mybatisProperties.getMapperLocations());
sqlSessionFactoryBean.setMapperLocations(resources);
} catch (IOException e) {
e.printStackTrace();
}
return sqlSessionFactoryBean;
}
}
3、 纯注解版事务编程
1. 原始对象 XXXService
<bean id="userService"class="com.xiaohe.service.UserServiceImpl">
<property name="userDAO" ref="userDAO"/>
</bean>
@Service
public class UserServiceImpl implements UserService{
@Autowired
private UserDAO userDAO;
}
2. 额外功能
<!--DataSourceTransactionManager-->
<bean id="dataSourceTransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
@Bean
public DataSourceTransactionManager dataSourceTransactionManager(DataSource dataSource){
DataSourceTransactionManager dstm = new DataSourceTransactionManager();
dstm.setDataSource(dataSource);
return dstm
}
3. 事务属性
@Transactional
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDAO userDAO;
4. 基于Schema的事务配置
<tx:annotation-driven transactionmanager="dataSourceTransactionManager"/>
@EnableTransactionManager ---> 配置Bean
1. ApplicationContext ctx = new
AnnotationConfigApplicationContext("com.xiaohe.mybatis");
SpringBoot 实现思想
2. 注解版MVC整合,SpringMVC中进⾏详细讲解
SpringMyBatis --->DAO 事务基于注解 --> Service Controller
org.springframework.web.context.ContextLoaderListener ---> XML⼯⼚ ⽆
法提供 new AnnotationConfigApplicationContex
第五章、Spring框架中YML的使⽤
1、什么是YML
YML(YAML)是⼀种新形式的配置⽂件,⽐XML更简单,⽐Properties更强⼤。
YAML is a nice human-readable format for configuration, and it has some useful hierarchical properties. It's more or less a superset of JSON,
so it has a lot of similar features.
2、Properties进⾏配置问题
1. Properties表达过于繁琐,⽆法表达数据的内在联系.
2. Properties⽆法表达对象 集合类型
3、YML语法简介
1. 定义yml⽂件
xxx.yml xxx.yaml
2. 语法
1. 基本语法
name: xiaohe
password: 123456
2. 对象概念
account:
id: 1
password: 123456
3. 定义集合
service:
- 11111
- 22222
4、 Spring与YML集成思路的分析
1. 准备yml配置⽂件
init.yml
name: xiaohe
password: 123456
2. 读取yml 转换成 Properties
YamlPropertiesFactoryBean.setResources( yml配置⽂件的路径 ) new
ClassPathResource();
YamlPropertiesFactoryBean.getObject() ---> Properties
3. 应⽤PropertySourcesPlaceholderConfigurer
PropertySourcesPlaceholderConfigurer.setProperties();
4. 类中 @Value注解 注⼊
5、Spring与YML集成编码
- 环境搭建
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.23</version>
</dependency>
最低版本 1.18
- 编码
1. 准备yml配置⽂件
2. 配置Bean中操作 完成YAML读取 与 PropertySourcePlaceholderConfigure
的创建
@Bean
public PropertySourcesPlaceholderConfigurer configurer() {
YamlPropertiesFactoryBean yamlPropertiesFactoryBean = new YamlPropertiesFactoryBean();
yamlPropertiesFactoryBean.setResources(new ClassPathResource("init.yml"));
Properties properties = yamlPropertiesFactoryBean.getObject();
PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
configurer.setProperties(properties);
return configurer;
}
3. 类 加⼊ @Value注解
4、Spring与YML集成的问题
1. 集合处理的问题
SpringEL表达式解决
@Value("#{'${list}'.split(',')}")
2. 对象类型的YAML进⾏配置时 过于繁琐
@Value("${account.name}")
SpringBoot @ConfigurationProperties