第二章 ---- spring注解开发
文章目录
- 参考视频
- 注解驱动的意义
- 常用注解(重点)
- 启动注解驱动
- IoC
- bean定义(@Component 、@Controller、@Service、 @Repository)
- @Scope
- bean生命周期(@PostConstruct、@PreDestroy)
- @Bean (加载第三方资源)
- DI
- 非引用类型注入(@Value)
- 引用类型注入(@Autowired、@Qualifier、@Primary、@Resource、@Inject、@Named)
- 集合注入(待查找)
- 加载第三方资源(@Bean)
- Druid数据源
- properties文件(@PropertySource)
- 注解驱动(@Configurable,@ComponentScan)
- 团队开发,第三方bean配置与管理(Import)
- bean加载控制
- bean的依赖关系(@DependsOn)
- 配置类加载顺序(@Order)
- bean的延迟加载(@Lazy)
- 应用场景
- 整合第三方技术(重点)
- 整合mybatis
- 整合Junit(注解)
- IOC底层核心原理
- IoC核心接口
- 组件扫描过滤器(@ComponentScan)
- ANNOTATION
- CUSTOM
- ASSIGNABLE_TYPE
- ASPECTJ
- REGEX
- 自定义导入器
- 自定义注册器
- bean初始化过程
参考视频
https://www.bilibili.com/video/BV1yq4y1N78E?spm_id_from=333.337.search-card.all.click
注解驱动的意义
常用注解(重点)
启动注解驱动
在核心配置文件中添加如下配置
<!--启动注解驱动:指定扫描路径,也就是资源所在的包-->
<context:component-scan base-package="com.zs"/>
说明:递归扫描,读取java文件,spring注解,将有bean注解的资源加入IoC容器
IoC
bean定义(@Component 、@Controller、@Service、 @Repository)
类注解
设置该类为spring管理的bean
<bean id="userService" class="com.zs.service.impl.UserServiceImpl"/>
@Service("userService")
public class UserServiceImpl implements UserService {
说明:@Controller、@Service、@Repository是@Component的衍生注解,功能同@Component,分别表示表现层,业务层,数据层
value:定义bean的访问id
@Scope
类注解
设置创建对象的模式,singleton或不写就是单例模式,prototype是多例模式
<bean id="userService" scope="prototype" class="com.zs.service.impl.UserServiceImpl"/>
@Service("userService")
@Scope("prototype")
public class UserServiceImpl implements UserService {
bean生命周期(@PostConstruct、@PreDestroy)
<bean id="userService" scope="prototype" init-method="init" destroy-method="destroy" class="com.zs.service.impl.UserServiceImpl"/>
@Service("userService")
@Scope("prototype")
public class UserServiceImpl implements UserService {@PostConstructpublic void init(){System.out.println("init...");}@PreDestroypublic void destroy(){System.out.println("destroy...");}
@Bean (加载第三方资源)
@Bean
方法注解
设置该方法的返回值作为spring管理的bean
说明:第三方bean无法在其原码上修改,使用@Bean引入,替换配置文件中静态工厂实例工厂创建bean,不区分方法是否为静态或非静态
<!--配置数据源--><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="${jdbc.driver}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></bean>
package com.zs.config;import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;@Component //此处后面会替换成专门的配置文件注解
public class JDBCConfig {@Bean("dataSource")public DruidDataSource getDataSource(){DruidDataSource ds = new DruidDataSource();ds.setDriverClassName("com.mysql.jdbc.Driver");ds.setUrl("jdbc:mysql://localhost:3306/testdb");ds.setUsername("iplat62");ds.setPassword("iplat62");return ds;}
}
DI
非引用类型注入(@Value)
@Value
属性注解、方法注解
设置对应属性的值或方法进行传参
<!--要注入的资源--><bean id="userDao" class="com.zs.dao.impl.UserDaoImpl"><property name="username" value="${username}"/><property name="password" value="${password}"/></bean>
package com.zs.dao.impl;import com.zs.dao.UserDao;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;@Repository("userDao")//别名不取默认为类名
public class UserDaoImpl implements UserDao {@Value("${username}")private String username;@Value("${password}")private String password;@Overridepublic void save() {System.out.println(username + "\t" + password);}
}
说明: value值支持读取properties文件中的属性值,通过类属性将properties中数据传入类中
value值支持SpEL
@value注解如果添加在属性上,可省略set方法(set方法的目的就是为属性赋值)
引用类型注入(@Autowired、@Qualifier、@Primary、@Resource、@Inject、@Named)
@Autowired、@Qualifier
属性,方法注解
设置对应属性的对象或对方法进行引用类型传参
相关属性:
- required: 定义该属性是否允许为null
@Autowired(required=false)
@Primary
类注解
设置类对应的bean按类型装配时优先装配
说明:设置多个类是会导致优先级无效,只能设置一个类优先
@Autowired //此时类型相同时会根据属性名自动识别
private UserDao userDao;@Repository("userDao")
public class UserDaoImpl implements UserDao{@Repository("userDao2")
public class UserDaoImpl2 implements UserDao{
匹配不到指定的bean,使用@Qualifier指定加载哪个bean
@Autowired //匹配不到
@Qualifier("userDao1")//指定引用哪个
private UserDao userDao;@Repository("userDao1")
public class UserDaoImpl implements UserDao{@Repository("userDao2")
public class UserDaoImpl2 implements UserDao{
bean不起名,默认使用类名
@Autowired //匹配不到,bean的名称没写默认是类名小写驼峰
private UserDao userDao;@Repository
public class UserDaoImpl implements UserDao{@Repository
public class UserDaoImpl2 implements UserDao{
指定优先加载的bean,只能用一个
@Autowired //匹配不到,bean的名称没写默认是类名小写驼峰
private UserDao userDao;@Repository
@Primary //优先加载该bean
public class UserDaoImpl implements UserDao{@Repository
public class UserDaoImpl2 implements UserDao{
@Inject、@Named、@Resource
说明:
- @Inject、@Named是 JSR330中的注解,与@Autowired、@Qualifier完全相同
- @Resource 是 JSR250 中的注解,可以简化书写格式
@Resource 相关属性
- name: 设置注入的bean的id
- type: 设置注入的bean的类型,接收的参数为Class类型
集合注入(待查找)
加载第三方资源(@Bean)
Druid数据源
<!--配置数据源--><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="${jdbc.driver}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></bean>
package com.zs.config;import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;@Component //此处后面会替换成专门的配置文件注解
public class JDBCConfig {@Bean("dataSource")public DruidDataSource getDataSource(){DruidDataSource ds = new DruidDataSource();ds.setDriverClassName("com.mysql.jdbc.Driver");ds.setUrl("jdbc:mysql://localhost:3306/testdb");ds.setUsername("iplat62");ds.setPassword("iplat62");return ds;}
}
properties文件(@PropertySource)
@PropertySource
类注解
加载properties文件中的属性值
package com.zs.config;import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;@Component
@PropertySource(value = {"classpath:jdbc.properties","a.properties"},ignoreResourceNotFound = true)
public class JDBCConfig {@Value("${jdbc.driver}")private String driver;@Value("${jdbc.url}")private String url;@Value("${jdbc.username}")private String username;@Value("${jdbc.password}")private String password;@Bean("dataSource")public DruidDataSource getDataSource(){DruidDataSource ds = new DruidDataSource();ds.setDriverClassName(driver);ds.setUrl(url);ds.setUsername(username);ds.setPassword(password);
// ds.setDriverClassName("com.mysql.jdbc.Driver");
// ds.setUrl("jdbc:mysql://localhost:3306/testdb");
// ds.setUsername("iplat62");
// ds.setPassword("iplat62");return ds;}
}
jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/testdb
jdbc.username=iplat62
jdbc.password=iplat62
说明:
- 不支持*通配格式,一旦加载,所有spring控制的bean中均可使用对应属性值
相关属性
- value:设置properties文件名
- ignoreResourceNotFound: 如果资源未找到,是否忽略,默认false
注解驱动(@Configurable,@ComponentScan)
@Configuration、@ComponentScan
类注解
设置当前类为spring核心配置类
@Configurable//替换核心配置文件
@ComponentScan("com.zs") //注解扫描
public class SpringConfig{}
团队开发,第三方bean配置与管理(Import)
@Import
类注解
导入第三方bean作为spring控制的资源
@Configurable
@Import(JDBCConfig.class) //导入数据源配置类
public class SpringConfig{}
加载配置类
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
bean加载控制
bean的依赖关系(@DependsOn)
@DependsOn
类注解、方法注解
控制bean的加载顺序,使其在指定bean加载完毕后再加载
@Service("userService")
@DependsOn("userDao")//加载Service,需要先加载dao
public class UserServiceImpl implements UserService{
说明:
- 配置在方法上,使@DependsOn指定的bean优先与@Bean配置的bean进行加载
- 配置在类上,使@DependsOn指定的bean优先与当前类中所有@Bean配置的bean进行加载
- 配置在类上,使@DependsOn指定的bean优先于@Component等配置的bean进行加载
配置类加载顺序(@Order)
配置类注解
控制配置类的加载顺序
@Order(1)
public class SpringConfig1{}@Order(2)
public class SpringConfig2{}ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig1.class,SpringConfig2.class);
bean的延迟加载(@Lazy)
类注解,方法注解
控制bean的加载时机,使其延迟加载
@Lazy
public class ClassName{}
应用场景
整合第三方技术(重点)
整合mybatis
JDBCConfig
package com.zs.config;import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;public class JDBCConfig {@Value("${jdbc.driver}")private String driver;@Value("${jdbc.url}")private String url;@Value("${jdbc.username}")private String username;@Value("${jdbc.password}")private String password;@Bean("dataSource")public DruidDataSource getDataSource(){DruidDataSource ds = new DruidDataSource();ds.setDriverClassName(driver);ds.setUrl(url);ds.setUsername(username);ds.setPassword(password);
// ds.setDriverClassName("com.mysql.jdbc.Driver");
// ds.setUrl("jdbc:mysql://localhost:3306/testdb");
// ds.setUsername("iplat62");
// ds.setPassword("iplat62");return ds;}
}
MybatisConfig
package com.zs.config;import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import javax.sql.DataSource;public class MybatisConfig {@Beanpublic SqlSessionFactoryBean getSqlSessionFactoryBean(@Autowired DataSource dataSource){SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();ssfb.setTypeAliasesPackage("com.zs.domain");ssfb.setDataSource(dataSource);return ssfb;}@Beanpublic MapperScannerConfigurer getMapperScannerConfigurer(){MapperScannerConfigurer msc = new MapperScannerConfigurer();msc.setBasePackage("com.zs.mapper");return msc;}
}
SpringConfig
package com.zs.config;import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;@Configurable
@ComponentScan("com.zs")
@Import({JDBCConfig.class,MybatisConfig.class})
@PropertySource(value = {"classpath:jdbc.properties","a.properties"},ignoreResourceNotFound = true)
public class SpringConfig {}
AccountServiceImpl
package com.zs.service.impl;import com.zs.mapper.AccountDao;
import com.zs.domain.Account;
import com.zs.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.List;@Service("accountService")
public class AccountServiceImpl implements AccountService {//注入dao@Autowiredprivate AccountDao accountDao;@Overridepublic void save(Account account) {accountDao.save(account);}@Overridepublic void delete(Integer id) {accountDao.delete(id);}@Overridepublic void update(Account account) {accountDao.update(account);}@Overridepublic List<Account> findAll() {return accountDao.findAll();}@Overridepublic Account findById(Integer id) {return accountDao.findById(id);}
}
AccountDao
package com.zs.mapper;import com.zs.domain.Account;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;import java.util.List;public interface AccountDao {@Insert("insert into account(name,money) values(#{name},#{money})")void save(Account account);@Delete("delete from account where id = #{id}")void delete(Integer id);@Update("update account set name=#{name},money=#{money} where id=#{id}")void update(Account account);@Select("select * from account")List<Account> findAll();@Select("select * from account where id=#{id}")Account findById(Integer id);
}
整合Junit(注解)
引入整合需要的坐标
<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>5.1.9.RELEASE</version></dependency>
UserServiceTest 创建测试类测试
package com.zs.service;import com.zs.config.SpringConfig;
import com.zs.domain.Account;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import java.util.List;//设定spring专用的类加载器
@RunWith(SpringJUnit4ClassRunner.class)
//加载核心配置文件
//@ContextConfiguration(value = {"classpath:applicationContext.xml"})
//设定加载的spring上下文对应的配置类
@ContextConfiguration(classes = SpringConfig.class)
public class UserServiceTest {@Autowiredprivate AccountService accountService;@Testpublic void testFindById(){Account ac = accountService.findById(1);}@Testpublic void testFindAll(){List<Account> all = accountService.findAll();all.forEach(System.out::println);}
}
IOC底层核心原理
IoC核心接口
- BeanFactory
提供bean的基本操作
- bean获取
- 按名称获取
- 按类型获取
- bean供应商
- bean基本信息
- 是否存在
- 是否单例
- 类型获取
- 类型检测
- 别名获取
- bean获取
- HierarchicalBeanFactory
提供bean分层结构,提出父子容器概念
- 获取本地bean
- AutowireCapableBeanFactory
提供bean自动装配功能
- bean创建
- bean装配
- 装配方式
- 前置动作
- 后置动作
- ListableBeanFactory
提供容器内部遍历搜索bean的功能
- 容器中的bean信息
- bean存在性
- bean的数量
- bean的类型
- bean相关信息获取
- 由类型获取bean的名称
- 由注解获取bean的名称
- bean信息获取
- bean的注解
- bean的定义名称
组件扫描过滤器(@ComponentScan)
@ComponentScan
类注解
设置spring配置加载类扫描规则
<dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.4</version></dependency>
ANNOTATION
@ComponentScan(value = "com.zs" //设置基础扫描路径excludeFilters = @ComponentScan.Filter( //设置过滤规则,过滤器type=FilterType.ANNOTATION //按注解过滤classes=Repository.class)
)
CUSTOM
@Configurable
@ComponentScan(value = "com.zs",excludeFilters = @ComponentScan.Filter(type= FilterType.CUSTOM,classes = MyTypeFilter.class))
public class SpringConfig {}
自定义过滤器
package com.zs.config.filter;import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;import java.io.IOException;public class MyTypeFilter implements TypeFilter {@Overridepublic boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {//true拦截,false 不拦截ClassMetadata classMetadata = metadataReader.getClassMetadata();String className = classMetadata.getClassName();if (className.equals("")){return true;}return false;}
}
ASSIGNABLE_TYPE
ASPECTJ
REGEX
自定义导入器
CustomerImportSelector (工具类,直接用)
配合文件 import.properties使用
path=com.zs.dao.impl.*
将自定义导入器使用Import导入主配置类上
package com.zs.config.selector;import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.filter.AspectJTypeFilter;
import org.springframework.core.type.filter.TypeFilter;import java.io.IOException;
import java.util.HashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Set;public class CustomerImportSelector implements ImportSelector {private String expression;public CustomerImportSelector(){try {//初始化时指定加载的properties文件名Properties loadAllProperties = PropertiesLoaderUtils.loadAllProperties("import.properties");//设定加载的属性名expression = loadAllProperties.getProperty("path");}catch (IOException e){e.printStackTrace();}}@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {//1.定义扫描包的名称String[] basePackages = null;//2.判断有@Import注解的类上是否有@ComponentScan注解if (importingClassMetadata.hasAnnotation(ComponentScan.class.getName())) {//3.取出@ComponentScan注解的属性Map<String, Object> annotationAttributes = importingClassMetadata.getAnnotationAttributes(ComponentScan.class.getName());//4.取出属性名称为basePackages属性的值basePackages = (String[]) annotationAttributes.get("basePackages");}//5.判断是否有此属性(如果没有ComponentScan注解则属性值为null,如果有ComponentScan注解,则basePackages默认为空数组)if (basePackages == null || basePackages.length == 0) {String basePackage = null;try {//6.取出包含@Import注解类的包名basePackage = Class.forName(importingClassMetadata.getClassName()).getPackage().getName();} catch (ClassNotFoundException e) {e.printStackTrace();}//7.存入数组中basePackages = new String[] {basePackage};}//8.创建类路径扫描器ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);//9.创建类型过滤器(此处使用切入点表达式类型过滤器)TypeFilter typeFilter = new AspectJTypeFilter(expression,this.getClass().getClassLoader());//10.给扫描器加入类型过滤器scanner.addIncludeFilter(typeFilter);//11.创建存放全限定类名的集合Set<String> classes = new HashSet<>();//12.填充集合数据for (String basePackage : basePackages) {scanner.findCandidateComponents(basePackage).forEach(beanDefinition -> classes.add(beanDefinition.getBeanClassName()));}//13.按照规则返回return classes.toArray(new String[classes.size()]);}
}
自定义注册器
使用方法同上,可以替换 扫描包的注解
package config.registrar;import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.filter.AspectJTypeFilter;
import org.springframework.core.type.filter.TypeFilter;import java.io.IOException;
import java.util.Map;
import java.util.Properties;public class CustomeImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {private String expression;public CustomeImportBeanDefinitionRegistrar(){try {//初始化时指定加载的properties文件名Properties loadAllProperties = PropertiesLoaderUtils.loadAllProperties("import.properties");//设定加载的属性名expression = loadAllProperties.getProperty("path");} catch (IOException e) {e.printStackTrace();}}@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {//1.定义扫描包的名称String[] basePackages = null;//2.判断有@Import注解的类上是否有@ComponentScan注解if (importingClassMetadata.hasAnnotation(ComponentScan.class.getName())) {//3.取出@ComponentScan注解的属性Map<String, Object> annotationAttributes = importingClassMetadata.getAnnotationAttributes(ComponentScan.class.getName());//4.取出属性名称为basePackages属性的值basePackages = (String[]) annotationAttributes.get("basePackages");}//5.判断是否有此属性(如果没有ComponentScan注解则属性值为null,如果有ComponentScan注解,则basePackages默认为空数组)if (basePackages == null || basePackages.length == 0) {String basePackage = null;try {//6.取出包含@Import注解类的包名basePackage = Class.forName(importingClassMetadata.getClassName()).getPackage().getName();} catch (ClassNotFoundException e) {e.printStackTrace();}//7.存入数组中basePackages = new String[] {basePackage};}//8.创建类路径扫描器ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(registry, false);//9.创建类型过滤器(此处使用切入点表达式类型过滤器)TypeFilter typeFilter = new AspectJTypeFilter(expression,this.getClass().getClassLoader());//10.给扫描器加入类型过滤器scanner.addIncludeFilter(typeFilter);//11.扫描指定包scanner.scan(basePackages);}
}
bean初始化过程
BeanFactoryPostProcessor
- 作用: 定义在bean工厂对象创建后,bean对象创建前执行的动作,用于对工厂进行创建后业务处理
- 运行时机:当前操作用于对工厂进行处理,仅运行一次
BeanPostProcessor
- 作用: 定义了所有bean初始化前后进行的统一动作,用于对bean进行创建前业务处理与创建后业务处理
- 运行时机:当前操作伴随着每个bean的创建过程,每次创建bean均运行该操作
InitializingBean
- 作用:定义了每个bean的初始化前进行的动作,属于非统一性动作,用于对bean进行创建前业务处理
- 运行时机:当前操作伴随着任意一个bean的创建过程,保障其个性化业务处理
注意:需要被spring容器加载方可运行
FactoryBean
- 对单一的bean的初始化过程进行封装,达到简化配置的目的
第二章 ---- spring注解开发相关推荐
- spring注解开发:容器中注册组件方式
1.包扫描+组件标注注解 使用到的注解如下,主要针对自己写的类 @Controller @Service @Repository @Component @ComponentScan 参考 spring ...
- SpringBoot学习笔记-2:第二章 Spring Boot 配置
第二章 Spring Boot 配置 1.YAML 配置 SpringBoot 全局配置文件 application.properties application.yml YAML 以数据为中心,比 ...
- 第二章 java常用开发工具以及程序的编写
2019独角兽企业重金招聘Python工程师标准>>> 第二章 java常用开发工具以及程序的编写 1. 程序的概念 2. java程序的开发的三个步骤 ...
- 关于Spring注解开发教程,打包全送你
摘要:spring是我们web开发中必不可少的一个框架,基于传统的xml方式配置bean总觉得太过繁琐,从spring2.5之后注解的出现可以大大简化我们的配置. 本文分享自华为云社区<如何高效 ...
- spring注解开发配置spring父子容器
spring注解开发配置spring父子容器 官网 https://docs.spring.io/spring-framework/docs/current/spring-framework-refe ...
- Android群英传笔记——第二章:Android开发工具新接触
Android群英传笔记--第二章:Android开发工具新接触 其实这一章并没什么可讲的,前面的安装Android studio的我们可以直接跳过,如果有兴趣的,可以去看看Google主推-Andr ...
- Spring注解开发学习笔记
1 IOC 1.1 工厂模式 使用工厂中方法代替new形式创建对象的一种设计模式 1.2 Inversion of Control控制翻转 一种思想,用于消减代码间的耦合. 实现思想:利用工厂设计模式 ...
- 尚硅谷Spring注解开发学习笔记
文章目录 前言 1.课程安排 1.1.容器 1.2.扩展原理 1.3.Web 2.配置文件开发 2.1.导入Spring-context依赖包 2.2.编写Spring配置文件 2.3.编写Perso ...
- Spring注解开发-Bean注册
1.使用注解开发我们需要在applicationContext.xml文件中添加context标签. 在配置文件中开启注解扫描. <?xml version="1.0" en ...
最新文章
- 超级账本(Hyperledger Fabric)源码分析之一:总览
- 博途v15安装过程中提示出错_博途V15.1安装及无限重启和.net3.5SP1错误处理解决方法...
- 计算机网络OSI架构详细图
- bom .dom_MicroProfile 2.2 BOM导入支持
- 使用GZIP和压缩数据
- 操作系统学习笔记-06-系统调用
- 山石网科-Hillstone-SC-***(SSL-***)之配置终结篇
- VUE基础(躺着都能会)
- 机器视觉中图像颜色识别理论
- 无线路由器的信道选择
- 无惧失败,做一只逆流而上的鱼
- 使用google-jib部署springboot应用到阿里云Serverless kubernetes
- 用python画小仓鼠教程_看看萌萌哒的仓鼠是怎么画出来的,最详细的图文教程,别错过!...
- 【教程】C++-赋值语句
- 我的世界服务器修改宠物属性,我的世界怎么改宠物名字?
- modbus slave和modbus poll使用说明
- 合法标识符(C语言)
- javascript——从「最被误解的语言」到「最流行的语言」
- markdown图片左对齐问题
- matlab求解微分代数方程组,微分代数方程(DAE)的Matlab 解法.PDF
热门文章
- 速成pytorch学习——4天中阶API示范
- hadoop入门简介
- AJAX框架衣柜推拉门设计,带镜子的推拉门衣柜如何设计好看
- 表格序号_让Excel表格中的序号自动更新,再也不怕删除、插入行了
- 外贸电商ERP都有哪些值得用?
- 初学Go语言的学生管理系统
- python接口自动化(四十三)-公共模块 pymysql 连接mysql数据库(单独说明)
- git bash linux 命令,Git Bash的妙用 - 使用Linux命令
- 怎么调出全局搜索_局部静态变量只能初始化一次?它是怎么实现的
- 计算机算法知识点总结,2021计算机考研知识点总结(1)