注解编程
01 什么是注解编程02 注解的作用 基础注解
01 注解扫描
1.1 排除方式1.2 包含方式 02 创建对象常用的注解
2.1 @Component2.2 @Scope2.3 @Lazy2.4 生命周期相关的注解 03 注入相关的注解
3.1 JDK 类型3.2 用户自定义类型 04 对于注解开发的思考 高级注解
01 配置Bean02 logback日志的整合
2.1 引入依赖2.2 引入logback的配置文件 03 @Bean
3.1 对象的创建3.2 类型注入
3.2.1 用户自定义类型注入3.2.2 JDK类型注入 3.3 控制对象的创建次数 04 @ComponentScan
4.1 基础使用4.2 排除策略的使用4.3 包含策略的使用 05 Spring工厂创建对象的多种配置方式
5.1 多种创建对象的方式5.2 多种创建对象的优先级 06 整合多个配置信息
6.1 为什么会有多个配置信息6.2 多配置信息整合的方式6.3 配置Bean的底层实现原理 四维一体的开发 注解编程 01 什么是注解编程
:::info
指的是在类或者方法上面加上特定的注解,完成特定功能的开发
使用注解开发方便,代码简洁,开发速度大大提供
:::
:::success
替换XML的这种配置形式,简化配置
:::
:::success
替换接口,实现双方 的契约型
:::
在Spring的配置文件,加入组件扫描器的标签,说明注解在项目中的位置,让Spring扫描这些包,让他们生效
1、spring的配置文件,会扫描当前包及其子包
2、扫描多个包的方式
使用多次组件扫描器,指定不同的包使用分割符; 或者是 ,分割多个包名指定父包
1.1 排除方式
排除策略可以叠加使用
annotation:排除特定的注解
org.springframework.stereotype.注解名:Service,Component等等 **aspectj**:切入点表达式,仅支持包切入点和类切入点assignable:排除特定的类型**regex**:正则表达式**custom**:自定义排除策略,框架底层开发
1.2 包含方式
作用:替换原来的Spring配置文件中的 id属性:在@Component 标签中提供了默认的设置方式, 首字母小写class属性:通过反射获得class的内容 属性value就是对象的名称,相当于bean标签的id,value值是唯一的;如果说,不指定value属性,id值就是单词首字母小写,是由Spring提供的Spring配置文件覆盖注解配置内容,注解和配置文件中,id值和class值要设置保持一致创建的对象在整个spring容器中只有一个当一个类不确定是什么功能的时候,使用Component注解 衍生注解 目的: 为了更准确的表示功能 @Repository:持久层注解,但是Spring整合Mybatis的过程中,不会使用这个注解或者@Component注解@Service:用在业务层类上面@Controller:控制层注解 2.2 @Scope 控制简单对象的创建次数如果说指定为 singleton ,就只会创建一次;这个值就是默认值如果说指定为 prototype,就会创建多次XML中 @Service@Scope(value = "singleton")public class UserServiceImpl implements UserService{} 位置在类上面,前提是有@Component注解 一般来说,Spring会在创建工厂的时候,创建所有单实例对象注意 一旦使用了@Lazy注解之后,Spring会在使用这个对象的时候,进行对象的创建 XML @Service@Lazypublic class UserServiceImpl implements UserService{} :::danger @PostConstruct public void init(){ System.out.println("User.init"); } 销毁方法:@PreDestroy @PreDestroy public void destroy(){ System.out.println("User.destroy"); } 注意事项 并不是Spring提供的注解,是JSR520提供的(JavaEE规范) 03 注入相关的注解 3.1 JDK 类型 **@Value** 1、设置 xxx.properties,配置相应的键的值2、Spring的工厂读取这个配置文件 :::success 不能应用于静态成员变量上,如果使用,获取的值为null不能注入集合类型,Spring有提供了新的配置形式。比如说YAML,YML 1、设置 xxx.properties2、在实体类上应用 @PropertySource("classpath:/xxx.properties")3、属性赋值 @Value("${key}") **@Autowired ** 在属性上面加入@Autowired在属性上面加入@Qualifier(value="bean的id"):表示使用指定名称的bean完成赋值 属性required 是一个boolean类型的,默认就是true,表示引用赋值失败,程序报错,并终止执行如果是false,说如果引用类型赋值失败,程序正常执行,引用类型是null一般情况下使用true,能够尽早的排查程序中的错误 可以放置在对应成员变量的set方法之上,也可以直接将这个注解放置在成员变量之上当放置在成员变量之上,通过反射直接对变量进行赋值,不会调用Set方法,这种方式比较推荐当放置在set方法之上,会执行set方法 **@Resource ** :::success @Configuration 用于替换XML配置文件@Configuration:类上加入这个注解,就成为了配置Bean;同样是@Component的衍生注解可以应用 # 方式一: 指定配置bean的Class,可以指定多个工厂ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class,AppConfig1.class);# 方式二: 指定配置bean所在的路径,工厂会扫描这个包,查找具有@Configuration注解的类型ApplicationContext ac = new AnnotationConfigApplicationContext("所在的包的路径"); :::danger <?xml version="1.0" encoding="UTF-8" ?> @Bean 注解在配置bean中进行使用,等同于Xml配置文件中的 标签 :::success 简单对象:直接能够通过new方式创建的对象复杂对象:不同直接通过new的方式创建的对象 简单对象 @Beanpublic 创建对象的类型 原来bean中的id值(){ // 方法体:创建对象 return 创建好的对象;} @Configurationpublic class MyApp { @Bean public User user(){ return new User(); }} @Bean@Scope("singleton")//控制对象的创建次数public Connection conn() { Connection conn = null; try { Class.forName("com.mysql.cj.jdbc.Driver"); conn = DriverManager.getConnection( "jdbc:mysql://localhost:3306/chat?serverTimezone=UTC", "root", "123456"); } catch (ClassNotFoundException | SQLException e) { e.printStackTrace(); } return conn;} // 方式一@Configurationpublic class AppConfig { @Bean public UserDao userDao(){ return new UserDaoImpl(); } @Bean public UserService userService(UserDao userDao){ UserServiceImpl userService = new UserServiceImpl(); userService.setUserDao(userDao); return userService; }}// 方式二@Configurationpublic class AppConfig { @Bean public User user(){ return new User(); } @Bean public UserMapper userMapper(){ return new UserMapperImpl(); } @Bean public UserService userService(){ UserServiceImpl userService = new UserServiceImpl(); userService.setUserMapper(userMapper()); userService.save(); return userService; }} @Configuration@PropertySource("classpath:/init.properties")public class AppConfig { @Value("${id}") private String id; @Value("${name}") private String name; @Bean public User user(){ User user = new User(); user.setId(id); user.setName(name); return user; }} @Bean@Scope("singleton | prototype") 默认值为singleton 在配置bean中进行使用,等同于在XML配置文件中的 注解方式:排除特定的注解:type = FilterType.ANNOTATION, value={}排除特定的类型:type = FilterType.ASSIGNABLE_TYPE , value={}切入点表达式:type = FilterType.ASPECTJ, pattern=""正则表达式:type = FilterType.REGEX, pattern=""自定义排除策略:type = FilterType.CUSTOM, value="" @Configuration@ComponentScan(basePackages = "com.study", excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,value = {Service.class})})public class AppConfig {} @ComponentScan(basePackages = "com.frame", useDefaultFilters = false, includeFilters = { @ComponentScan.Filter(type = FilterType.ANNOTATION,value = {Service.class}) } ) 主要用于程序员自己开发的类型 **方式二:@Bean ** 框架提供的类型,别的程序员提供的类型 方式三:xml配置文件 与遗留系统整合的时候,在纯注解的开发过程中,基本不会使用 **方式四:@import ** 创建单个对象,会在Spring框架底层进行使用 5.2 多种创建对象的优先级 @Component 及其衍生注解 < @Bean < XML配置优先级高的配置,会覆盖优先级低的注解;前提是id值相同通过配置优先级,可以解决基于注解进行配置的耦合问题,如果说对一个类不满意,可以使用优先级高的进行覆盖 :::info :::success 基于basePackages包扫描的方式 ApplicationContext ac = new AnnotationConfigApplicationContext("包名"); @import在一个配置Bean中引入另一个配置Bean,相当于 // 选择AppConfig1 作为主配置文件@Configuration@import(AppConfig.class)public class AppConfig1 { @Bean public Student student(){ return new Student(); }}// 创建工厂ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig1.class); 在工厂创建的时候,指定多个配置Bean的class对象 ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig1.class,AppConfig2.class); :::success 在应用配置Bean的过程中,不管使用哪种方式进行配置信息的汇总,其操作方式都是通过成员变量加上@Autowired注解完成的 @Configuration@import(AppConfig2.class)public class AppConfig1 { @Autowired private UserMapper userMapper; @Bean public UserService userService(){ UserServiceImpl userService = new UserServiceImpl(); userService.setUserMapper(userMapper); return userService; }}@Configurationpublic class AppConfig2 { @Bean public UserMapper userMapper(){ return new UserMapperImpl(); }} :::success @Componentpublic class UserMapperImpl implements UserMapper{}@Configuration@import(AppConfig2.class)@ComponentScan("注解扫描的包")public class AppConfig1 {} :::success 遗留系统的整合配置覆盖 public class UserDAOImpl implements UserDAO{} Spring 在配置Bean中加入@Configuration注解之后,底层就会通过Cglib的代理方式,来进行对象相关的配置处理 :::info
:::success
本质上这些衍生注解就是@Component,作用,细节,用法都是一致的
:::
这两个注解并不是Spring提供的,是JSR520(JavaEE规范)提供的
:::
初始化方法:@PostConstruct
:::info
用于JDK基本类型的赋值
:::
:::
**@PropertySource **
:::info
1、用于替换Spring配置文件中的
:::
04 对于注解开发的思考 Spring注解配置 和 配置文件配置是互通的在程序员开发的类型上,可以加入对应的注解,进行对象的创建应用其他程序员开发的类型时,还是需要使用配置文件进行配置
高级注解
Spring 3.X 以上
:::
基于注解开发的时候,不能够集成Log4j
:::
3.1 对象的创建
@Bean(“id值”) -------如果说不指定这个id值,方法名就是id值
:::
对象的创建
复杂对象
4.2 排除策略的使用
**方式一:@Component **
06 整合多个配置信息 6.1 为什么会有多个配置信息
拆分多个配置bean的开发,是一种模块化开发的形式,也体现了面向对象各司其职的设计思想
:::
多个配置Bean
:::
跨配置进行注入:通过提供成员变量并且使用@Autowired进行注入
:::
配置Bean与@Component相关注解的整合
:::
配置Bean与Spring的XML配置文件的整合
:::
Spring在开发一个功能的时候,有四种形式,虽然说开发方式不同,但是最终的效果是一样的
:::