spring注解开发最全总结!(学springboot前看一下手撕源码!)

Posted 结构化思维wz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring注解开发最全总结!(学springboot前看一下手撕源码!)相关的知识,希望对你有一定的参考价值。

github地址,不要吝啬☆(可以下载PDF)
CSDN下载地址

学springboot前复习一下,直接起飞!!对比总结!!参考suns最强spring教学!

1.关于包扫描

@Configuration
@ComponentScan(basePackages = "com.baizhiedu.scan")
public class AppConfig2 {
}
<context:component-scan base-package=""/>
  • 排除

    <context:component-scan base-package="com.baizhiedu">
     <context:exclude-filter type="assignable"
    expression="com.baizhiedu.bean.User"/>
    </context:component-scan>
    @ComponentScan(basePackages = "com.baizhiedu.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.baizhiedu" use-default-filters="false">
     <context:include-filter type="" expression=""/>
    </context:component-scan>
    @ComponentScan(basePackages = "com.baizhiedu.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
    

2.@Configuration—替换spring配置文件 <beans

  • Spring3.x提供的新的注解,⽤于替换XML配置⽂件。
    此注解会告诉spring这是配置类
    此步骤相当于创建了一个applicationContext.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.baizhiedu");
    
  • 配置bean能替换以前xml文件的什么呢?

    1.创建对象
    2.注入
    3.定义注解的扫描
    4.引入其他配置文件
    
  • 注意的细节

    不能集成 log4j
    可以集成logback
    logback:1.导入相关依赖 2.引入logback配置文件
    
  • @Configuration注解的本质

  • 本质:也是@Component注解的衍⽣注解
    可以应⽤<context:component-scan进⾏扫描
    

2.对象创建相关注解

1.@Component

  1. 搭建开发环境

    • 想让spring框架在这时包及其自保重扫描对应的注解,使其生效需要在spring配置文件中写入:
    <context:component-scan base-package="要扫描的包"/>
    
    • @ComponentScan
  2. @Component 相当于以前spring配置文件中的<bean 标签

    <bean  id=""  class=""  />
    id 属性 @Component提供默认id---> 首单词字母小写(UserDao--->userDao)
    class 属性 @Component写在哪个class上会通过反射获得
    
  3. @Component(“指定id”) 可以通过此种方式指定id

  4. @Component的衍生注解

    @Repository  用于Dao层(spring与mybatis整合后中不使用注解创建对象)
    @Service     用于service层
    @Controller  用于controller层
    
  5. @Scope注解 ----- 控制简单对象的创建次数

    默认为 singleton 单例模式

  6. @Lazy注解 ----- 延迟创建单例对象

    一旦使用了@Lazy注解后,spring会在使用这个对象的时候,进行对象的创建

  7. 生命周期相关注解

    1.初始化相关方法@PostConstruct
    2.销毁方法     @DisposableBean
    这两个方法并不是spring提供的,是JSR520提供
    

2.@Bean注解

  • 相当于<bean标签

  • 基本使用:

    @Bean
    Public User user(){      //User--创建对象类型  user 方法名==id属性
        return new User();  //把对象的创建代码写在方法体中
    }
    // 大前提得在配置bean里(有@Configuration)
    // 自定义id值 ---  @Bean("id")
    // 控制创建次数 --- @Bean("singleton|prototype") 默认单例
    
    
  • 提出疑问:class怎么对应,如果不同包下同类名怎么办??

    idea会让你选是在哪个包下
    return new com.it.Dog();
    

3.@Import 了解即可 (spring底层使用)

4.这三种什么时候使用?

1.@Component @Autowired  用于程序员自己开发的类;
		例如:UserService UserDao 等
2.@Bean 多用于复杂对象,框架提供的类型,别的程序员开发的类型(没有源码)
		例如:SqlSessionFactoryBean
3.<bean id="" class="" /> 一般不使用,多用于遗留系统的整合

5.配置优先级

@Component及其衍⽣注解 < @Bean < 配置⽂件bean标签
优先级⾼的配置 覆盖优先级低配置
@Component
public class User{
}
@Bean
public User user(){
 return new User();
}
<bean id="user" class="xxx.User"/>
配置覆盖:id值 保持⼀致

6.基于注解配置的耦合问题

原有的开发方式:
@Configuration
public class AppConfig4 {
 @Bean
 public UserDAO userDAO() {
 return new UserDAOImpl();
 }
}
解决办法一:在这个配置bean上添加(有耦合)@ImportResource("applicationContext.xml")
    
解决办法二:新建一个配置bean
 @Configuration
@ImportResource("applicationContext.xml")
public class AppConfig5{
 
}
 ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class,新建的配置bean);
applicationContext.xml
<bean id="userDAO"
class="com.baizhiedu.injection.UserDAOImplNew"/>

3.注入相关注解

1.1用户自定义类型@Autowired

@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

1.2.JDK类型@value

@Value注解
1. 设置xxx.properties
 id = 10
 name = suns
2.1 Spring的⼯⼚读取这个配置⽂件
 <context:property-placeholder location=""/>
2.2 @PropertySource("properties位置")
3. 代码
 属性 @Value("${key}"

注意:

  • @value不能应用在静态成员变量上
    @value+properties这种方式,不能注入集合类型(下面会引入YAML)
    

2.1 @Bean 用户自定义类型注入

  • 把userDao 注入到 userService中

    //简化写法
    @Bean
    public UserService userService() {
     UserServiceImpl userService = new UserServiceImpl();
     userService.setUserDAO(userDAO());
     return userService;
    }
    

2.2@Bean jdk类型注入

  • @Bean
    public Customer customer() {
     Customer customer = new Customer();
     customer.setId(1);
     customer.setName("xiaohei");
     return customer;
    }
    

    注意:如果直接用set方法,会存在耦合问题

  • 配合配置文件使用

    @Configuration
    @PropertySource("classpath:/init.properties")
    public class AppConfig1 {
     @Value("${id}")
     private Integer id;
     @Value("${name}")
     private String name;
     @Bean
     public Customer customer() {
     Customer customer = new Customer();
     customer.setId(id);
     customer.setName(name);
     return customer;
     }
    }
    

4.整合多个配置信息

按照功能会分成多个配置bean(模块化编程的思想,面向对象各司其职)

  • 如何使多种配置信息 汇总成一个整体??
  • 如何实现跨配置的注入???

1.配置bean与配置bean整合

  • 曾经xml文件的整合方式

    ApplicationContext ctx = new ClassPathXmlApplicationContext("application-*.xml");
    
  • 现在整合配置bean的方式1—基于包扫描

     ApplicationContext ctx = new
    AnnotationConfigApplicationContext("com.config");
    
  • 方式2 — @Import —

    @Configuration
    @Import(AppConfig2.class)
    public class AppConfig1{
    	@Bean
    	public User user(){
    		return new User();
    	}
    }
    
    ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig1);
    
  • 方式3 ---- 创建工厂时指定多个bean的class对象【不推荐使用】

    ApplicationContext ctx = new
    AnnotationConfigApplicationContext(AppConfig1.class,AppConfig2
    .class);
    

    跨配置进行注入

    在应⽤配置Bean的过程中,不管使⽤哪种⽅式进⾏配置信息的汇总,其操作⽅式都是通过
    成员变量加⼊@Autowired注解完成。
    @Configuration
    @Import(AppConfig2.class)
    public class AppConfig1 {
     @Autowired
     private UserDAO userDAO;
     @Bean
     public UserService userService() {
     UserServiceImpl userService = new UserServiceImpl();
     userService.setUserDAO(userDAO);
     return userService;
     }
    }
    
    @Configuration
    public class AppConfig2 {
     @Bean
     public UserDAO userDAO() {
     return new UserDAOImpl();
     }
    }
    

2.配置Bean与@Component整合

只需要加上注解的扫描!

@Component@Repository
public class UserDAOImpl implements UserDAO{
 
}

@Configuration
@ComponentScan("")
public class AppConfig3 {
 
 @Autowired
 private UserDAO userDAO;
 @Bean
 public UserService userService() {
 UserServiceImpl userService = new UserServiceImpl();
 userService.setUserDAO(userDAO);
 return userService;
 }
}

ApplicationContext ctx = new
AnnotationConfigApplicationContext(AppConfig3.class)

3.配置Bean与spring配置文件整合

  • 配置覆盖
  • 遗留系统的整合
1. 遗留系统的整合 2. 配置覆盖
 
public class UserDAOImpl implements UserDAO{
 
}
<bean id="userDAO" class="com.baizhiedu.injection.UserDAOImpl"/>
@Configuration
@ImportResource("applicationContext.xml")
public class AppConfig4 {
 
 @Autowired
 private UserDAO userDAO;
 @Bean
 public UserService userService() {
 UserServiceImpl userService = new UserServiceImpl();
 userService.setUserDAO(userDAO);
 return userService;
 }
}
ApplicationContext ctx = new
AnnotationConfigApplicationContext(AppConfig4.class);

5.配置Bean底层实现原理

Spring在配置Bean中加⼊了@Configuration注解后,底层就会通过Cglib的代理⽅式,来进
⾏对象相关的配置、处理

纯注解版AOP编程

1.搭建环境

1.应用配置Bean
2.注解扫描

2.开发步骤

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;
 }
 }
3. Spring的配置⽂件中
 <aop:aspectj-autoproxy />
 @EnableAspectjAutoProxy ---> 配置Bean

细节分析

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整合

基础配置(配置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/suns?
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.baizhiedu.entity"></property>
 <property name="mapperLocations">
 <list>
<value>classpath:com.baizhiedu.mapper/*Mapper.xml</value>
 </list>
 </property>
 </bean>
 --------------------------------------------------
 @Bean
 public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){
 SqlSessionFactoryBean sqlSessionFactoryBean = newSqlSessionFactoryBean();
 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.baizhiedu.dao">
</property>
 </bean>
 -------------------------------------------------------
 @MapperScan(basePackages={"com.baizhiedu.dao"}) ---> 配置bean完成

编码

  1. 实体
  2. Dao接口
  3. Mapper文件
  • MapperLocations编码时通配的写法

    //设置Mapper⽂件的路径
    sqlSessionFactoryBean.setMapperLocations(Resource..);
    Resource resouce = new ClassPathResouce("UserDAOMapper.xml")
     
    sqlSessionFactoryBean.setMapperLocations(new ClassPathResource("UserDAOMapper.xml"));
    -------------------------------------------------
    <property name="mapperLocations">
     <list>
     <value>classpath:com.baizhiedu.mapper/*Mapper.xml</value>
     </list>
    </property>
    -------------------------------------------------------------------
    ⼀组Mapper⽂件
    ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
    Resource[] resources = resolver.getResources("com.baizhi.mapper/*Mapper.xml");
    sqlSessionFactoryBean.setMapperLocations(resources)
    

    配置Bean数据耦合问题

    配置文件:

    mybatis.driverClassName = com.mysql.jdbc.Driver
    mybatis.url = jdbc:mysql://localhost:3306/suns?useSSL=false
    mybatis.username = root
    mybatis.password = 123456
    mybatis.typeAliasesPackages = com.baizhiedu.mybatis
    mybatis.mapperLocations = com.baizhiedu.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以上是关于spring注解开发最全总结!(学springboot前看一下手撕源码!)的主要内容,如果未能解决你的问题,请参考以下文章

    2020年最全Spring面试题总结,“金三银四”戴上口罩不畏惧!

    史上最全 69 道 Spring 面试题和答案

    Spring Boot - 访问外部接口最全总结

    Spring开发中常用的注解总结

    Spring常用注解总结

    Spring常用注解总结