学习视频:【孙哥说Spring5:从设计模式到基本应用到应用级底层分析,一次深入浅出的Spring全探索。学不会Spring?只因你未遇见孙哥】
Spring在3.x提供的新的注解,用于替换XML配置文件。
@Configuration
public classAppConfig{
}
问题:
AnnotationConfigApplicationContext
1.创建工厂代码
ApplicationContext ctx = new AnnotationConfigApplicationContext();
2.指定配置文件
1. 指定配置bean的Class
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
2. 指定配置bean所在的路径
ApplicationContext ctx = new AnnotationConfigApplicationContext("com.baizhi");
基于注解开发使用日志
不能集成Log4j(落后了)
集成新的日志技术:logback
引入相关jar
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-apiartifactId>
<version>1.7.26version>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>jcl-over-slf4jartifactId>
<version>1.5.6version>
dependency>
<dependency>
<groupId>ch.qos.logbackgroupId>
<artifactId>logback-classicartifactId>
<version>1.2.12version>
dependency>
<dependency>
<groupId>ch.qos.logbackgroupId>
<artifactId>logback-coreartifactId>
<version>1.2.12version>
dependency>
<dependency>
<groupId>org.logback-extensionsgroupId>
<artifactId>logback-ext-springartifactId>
<version>0.1.5version>
dependency>
引入logback配置文件(logback.xml)
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} {%thread} %-5level %logger{50} - %msg%npattern>
encoder>
appender>
<root level="DEBUG">
<appender-ref ref="STDOUT"/>
root>
configuration>
@Configuration注解的本质
本质:也是@Component注解的衍生注解
可以应用
@Bean注解在配置bean中进行使用,等同于XML配置文件中的
1. 简单对象
直接能够通关new方式创建的对象:User UserService UserDAO
2. 复杂对象
不能通过new方式创建的对象:Connection SqlSessionFactory
```java
/**
* 创建复杂对象
* Connection 不能直接通过new 创建
*/
@Bean
public Connection conn() {
Connection conn = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/myschool?useSSL=false", "root", "123456");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
```
- @Bean注解创建复杂对象的注意事项
```java
遗留系统整合比较常见,自己写还是通过上面的方式
@Bean
public Connection conn1(){
Connection conn = null;
try {
ConnectionFactoryBean factoryBean = new ConnectionFactoryBean();
conn = factoryBean.getObject();
} catch (Exception e) {
e.printStackTrace();
}
return conn;
}
```
自定义id值
@Bean("id)
控制对象创建次数
@Bean
@Scope("singleton | prototype") 默认值 singleton
用户自定义类型
@Bean
public UserDao userDAO(){
return new UserDaoImpl();
}
//可以通过形参传入userDao,也可以调用方法获取userDao
@Bean
public UserService userService(){
UserServiceImpl userService = new UserServiceImpl();
userService.setUserDao(userDAO());
return userService;
}
JDK类型的注入
@Bean
public Customer customer(){
Customer customer = new Customer();
customer.setId(1);
customer.setName("xiaohei");
return customer;
}
JDK类型注入的细节分析
如果直接在代码中进行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;
}
}
@ComponentScan注解在配置bean中进行使用,等同于xml配置中的context:component-scan标签
目的:进行相关注解的扫描 @Component @Value…
@Configuration
@ComponentScan(basePackages = "com.baizhi.scan")
public class AppConfig2 {
}
等价于: <context:component-scan base-package=""/>
排除
@Configuration
@ComponentScan(basePackages = "com.baizhi.scan",
excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,value = {Service.class})
,@ComponentScan.Filter(type = FilterType.ASPECTJ,pattern = "*..User1")})
// 第一个排除Service注解,排除了user2对象,第二个排除了User1类
public class AppConfig2 {
}
注意**:针对ASPECTJ和REGEX后面的值是pattern,其他都是value**
包含
@ComponentScan(basePackages = "com.baizhi.scan",
useDefaultFilters = false,//放弃默认扫描策略,必须指定为false
includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,value = {Service.class})})
public class AppConfig2 {
}
@Component及其衍生注解 < @Bean < 配置文件bean标签
优先级高的配置 覆盖优先级低的配置(如果对@Component注解的类不满意,可以用@Bean注解的类进行覆盖,但是id必须同名)
@ImportResource("applicationContext.xml")// 与spring配置文件集成,先读取配置@Bean 在读取配置文件
@Configuration
@ImportResource("applicationContext.xml")
public class AppConfig4 {
@Bean
public UserDao userDao() {
return new UserDaoImpl();
}
}
**在applicationContext.xml 配置bean解耦合**
<bean id="userDAO" class="com.baizhi.injection.UserServiceImplNew"/>
这样产生的问题,还是会有耦合,因为要在原有的AppConfig配置类添加集成代码,解决方法:
// 新建立一个AppConfig5的配置类,将集成代码放到此类中,再读取多个配置类,可以根据包地址读取所有的配置类
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig4.class,AppConfig5.class);
ApplicationContext ctx1 = new AnnotationConfigApplicationContext("com.baizhi");
UserDao userDao = (UserDao) ctx.getBean("userDAO");
userDao.save();
为什么会有多个配置信息
根绝不同类型(事务、数据库连接)拆分多个配置bean的开发,是一种模块化开发的形式,也体现了面向对象各司其职的设计思想
多配置信息整合的方式
整合多种配置
2. @Import
1. 可以创建对象
2. 多配置bean的整合
3. 在工厂创建时,指定多个配置Bean的Class对象
```java
// 这种方式日常开发使用较少,了解即可
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig4.class,AppConfig5.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();
}
}
适用于应用配置Bean的所有场景
@Component(@Repostitory)
public class UserDAOImpl implements UserDAO{
}
@Configuration
@ComponentScan("")
public lcass AppConfig3{
@Autowired
private UserDao userDao;
@Bean
public UserService userService() {
UserServiceImpl userService = new UserServiceImpl();
userService.setUserDao(userDao);
return userService;
}
}
1.遗留系统的整合
2.配置覆盖
<bean id="userDAO" class="com.baizhi.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;
}
}
Spring在配置Bean加入了@Configuration注解后,底层就会通过Cglib的代理方式,来进行对象相关的配置、处理
下一章:Spring5学习随笔-纯注解开发、YML详解