兜兜转转用了一个半月的时间又把Spring相关的知识重新缕了一遍,这次回看明显和大学刚学时的感触是不同的,可能是技术变好了,有些坑没踩就过了,前面10节遇到的问题不太多,可能AOP底层这块理解的还是不太好。以后再回看需要重点看的章节应该是Spring(10)。算是Spring IOC这块的纯注解写法,和SpringBoot启动注解的一个简单分析,当然没有前面9节的知识做铺垫,第10节很多是看不懂的。
这节主要记记剩下的,纯注解整合事务、AOP、MyBatis,yml的写法。现在纯注解整合SSM还是暂时做不到的,因为controller层这块,创建工厂还是需要web.xml进行配置,这个问题会在日后整合springmvc或者springboot时分析解决。
一、纯注解版AOP编程
其实参照前几节有一个半注解整合SSM,Spring(8),事务是基于AOP的,而且使用注解代替了大量标签,AOP也是一样,只需将配置文件中的标签(Spring(5)AOP编程)替换成注解即可
Spring的配置⽂件中
<aop:aspectj-autoproxy />
@EnableAspectjAutoProxy ---> 配置Bean
两段关键的代码,一个是切面类,一个是配置bean:
package com.jin.aop.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
/**
* @author jinyunlong
* @date 2021/12/30 14:02
* @profession ICBC锅炉房保安
*/
@Aspect
@Component
public class MyAspect {
@Pointcut("execution(* com.jin.aop..*.*(..))")
public void pointCut(){}
@Around("pointCut()")
public Object arround(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("----Log----");
Object proceed = joinPoint.proceed();
return proceed;
}
}
package com.jin.aop;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
/**
* @author jinyunlong
* @date 2021/12/30 13:37
* @profession ICBC锅炉房保安
*/
@Configuration
@ComponentScan(basePackages = "com.jin.aop")
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class AppConfig {
}
细节分析:
1. 代理创建⽅式的切换 JDK Cglib
<aop:aspectj-autoproxy proxy-target-class=true|false />
@EnableAspectjAutoProxy(proxyTargetClass)
2. SpringBoot AOP的开发⽅式
@EnableAspectjAutoProxy 已经设置好了
1. 原始对象
@Service(@Component)
public class UserServiceImpl implements UserService{
}
2. 创建切⾯类 (额外功能 切⼊点 组装切⾯)
@Aspect
@Component
public class MyAspect {
@Around("execution(* login(..))")
public Object arround(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("----aspect log ------");
Object ret = joinPoint.proceed();
return ret;
}
}
Spring AOP 代理默认实现 JDK SpringBOOT AOP 代理默认实现 Cglib
二、纯注解版Spring+MyBatis整合
见Spring(6)的一大堆标签配置,Spring3.x终于可以通过@Configuration去使用@Bean自定义复杂对象了,所以直接写好复杂对象返回即可:
package com.jin.mybatis;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import java.io.IOException;
/**
* @author jinyunlong
* @date 2021/12/30 15:31
* @profession ICBC锅炉房保安
*/
@Configuration
@ComponentScan("com.jin.mybatis")
@MapperScan(basePackages = "com.jin.mybatis")
public class MyBatisAutoConfiguration {
@Autowired
private MybatisProperties mybatisProperties;
@Bean
public DataSource dataSource(){
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName(mybatisProperties.getDriver());
druidDataSource.setUrl(mybatisProperties.getUrl());
druidDataSource.setUsername(mybatisProperties.getUsername());
druidDataSource.setPassword(mybatisProperties.getPassword());
return druidDataSource;
}
@Bean
public SqlSessionFactoryBean sqlSessionFactoryBean() throws IOException {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource());
sqlSessionFactoryBean.setTypeAliasesPackage(mybatisProperties.getType());
// sqlSessionFactoryBean.setMapperLocations(new ClassPathResource("UserDAOMapper.xml"));
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource[] resources = resolver.getResources(mybatisProperties.getMapper());
sqlSessionFactoryBean.setMapperLocations(resources);
return sqlSessionFactoryBean;
}
}
干净又卫生啊,这个类还解决了mapper.xml文件的通配问题和数据解耦合问题;
package com.jin.mybatis;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
/**
* @author jinyunlong
* @date 2021/12/30 16:58
* @profession ICBC锅炉房保安
*/
@Component
@PropertySource("classpath:mybatis.properties")
public class MybatisProperties {
@Value("${mybatis.DriverClassName}")
private String driver;
@Value("${mybatis.url}")
private String url;
@Value("${mybatis.username}")
private String username;
@Value("${mybatis.password}")
private String password;
@Value("${mybatis.typeAliasesPackages}")
private String type;
@Value("${mybatis.mapperLocations}")
private String mapper;
public String getDriver() {
return driver;
}
public void setDriver(String driver) {
this.driver = driver;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getMapper() {
return mapper;
}
public void setMapper(String mapper) {
this.mapper = mapper;
}
}
通配写法:
mybatis.mapperLocations = com.jin.mapper/*Mapper.xml
注:之前MapperScannerConfigure标签(创建DAO对象用的)直接变成@MapperScan注解了
三、纯注解版事务编程
相比于之前的半注解,纯注解事务编程需要修改两个地,一个是额外功能复杂对象的创建不用标签了,另一个是组装切面的标签变成注解了:
package com.jin.mybatis;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
/**
* @author jinyunlong
* @date 2022/1/4 16:20
* @profession ICBC锅炉房保安
*/
@Configuration
@EnableTransactionManagement
@Import(MyBatisAutoConfiguration.class)
public class TranscactionAutoConfiguration {
@Autowired
private DataSource dataSource;
@Bean
public DataSourceTransactionManager dataSourceTransactionManager(){
DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
dataSourceTransactionManager.setDataSource(dataSource);
return dataSourceTransactionManager;
}
}
@Import(MyBatisAutoConfiguration.class)
这个注解不加,注入dataSource会找不到,不过不加也没事,IDEA智能识别的事。
<tx:annotation-driven transactionmanager="dataSourceTransactionManager"/>
@EnableTransactionManager ---> 配置Bean
到这里大部分的XML都可以用注解整合了,还剩controller层没做,暂时还不行,以后在SpringMVC或者SpringBoot时再做分析。
四、Spring框架中YML的使用
YML的概念:YML(YAML)是⼀种新形式的配置文件,比XML更简单,比Properties更强大。
Properties进行配置问题:Properties表达过于繁琐,无法表达数据的内在联系;Properties无法表达对象、集合类型
YML语法:
1. 定义yml⽂件
xxx.yml xxx.yaml
2. 语法
1. 基本语法
name: suns
password: 123456
2. 对象概念
account:
id: 1
password: 123456
3. 定义集合
service:
- 11111
- 22222
测试代码:
引依赖:
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.25</version>
</dependency>
最低版本1.18
account:
name: jinjin
password: 78787878
list: 123,456,789
package com.jin.yml;
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.io.ClassPathResource;
import java.util.Properties;
/**
* @author jinyunlong
* @date 2022/1/5 14:19
* @profession ICBC锅炉房保安
*/
@Configuration
@ComponentScan("com.jin.yml")
public class YmlAutoConfiguration {
@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;
}
}
本质是取到了yml文件转换成Properties再应用到PropertySourcesPlaceholderConfigurer中去
package com.jin.yml;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @author jinyunlong
* @date 2022/1/5 14:25
* @profession ICBC锅炉房保安
*/
@Component
public class Account {
@Value("${account.name}")
private String name;
@Value("${account.password}")
private String password;
// @Value("${list}")
@Value("#{'${list}'.split(',')}")
private List<String> list;
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
//用于测试:YML
@Test
public void test3(){
ApplicationContext ctx = new AnnotationConfigApplicationContext("com.jin.yml");
Account account = (Account) ctx.getBean("account");
// System.out.println("account.getName() = " + account.getName());
// System.out.println("account.getPassword() = " + account.getPassword());
List<String> list = account.getList();
for (String s : list){
System.out.println("s = " + s);
}
}
Spring与YML集成的问题:
1. 集合处理的问题
SpringEL表达式解决
@Value("#{'${list}'.split(',')}")
2. 对象类型的YAML进⾏配置时 过于繁琐
@Value("${account.name}")
这个问题暂时没法解决
SpringBoot 的@ConfigurationProperties可以解决上述两个问题
五、总结
至此记了十一节,Spring的一些基础就记完了,模拟一个场景就是在软考高级做案例分析题时,让你根据工厂、代理 ;接口、反射;解耦、拓展 这几个关键词去简述Spring的相关概念,自己能不能扩写清楚,就是对这十几节学习成果的反馈,当然重要的还是实操,还是要逐行去写代码,一点一点的去熟悉,遇到报错或者不明白的地方再回看,查缺补漏。
2022年开始了,平常也是工作之余学学,还有个140小时的JVM想看一看,70小时的谷粒商城想扫一扫,50小时的web渗透想整一整,那我接下来选择再去看看SpringMVC,时间比较短,日常也在用,看起来比较快。剩下的这些东西,就作为2022年的学习计划吧。(数据分析遥遥无期)