新博客:https://blog.bigdataboy.cn/article/453.html什么是事务事务是逻辑上的一组操作,主要是对数据库的数据的操作,要么都执行,要么都不执行,重点是都,所以当这组操作不一致时,那么就自动进行回滚,把数据恢复到这组操作之前,这样数据库的数据就不会出错了。转账案例事务这个概念最早是在数据库接触到,但是感觉并不明显,这里可以通过这个案例感受一下a给b转账100正常情况a的余额减少100b的余额增加100publicvoidtransfer(Stringout,Stringin,Doublemoney){//转账accountDao.inMoney(in,money);accountDao.outMoney(out,money);}如果在转账过程中出现异常,不使用事务的话,就会出现,一方钱减少了,而另一方确没有增加publicvoidtransfer(Stringout,Stringin,Doublemoney){//转账accountDao.inMoney(in,money);//期间出现报错accountDao.outMoney(out,money);}Spring事务处理第一步、定义该函数需要事务处理,在接口上定义项目使用的DataSource要一样,不然事务无法实现,案例中指MyBatis初始化SqlSessionFactoryBean时传入的DataSource和JDBC交给Spring的事务的DataSource一致publicinterfaceAccountService{@Transactional//该注解开启事务publicvoidtransfer(Stringout,Stringin,Doublemoney);}第二步、在JdbcConfig类,定义事务管理Bean交给Spring容器管理@ConfigurationpublicclassJdbcConfig{@Value("${jdbc.driver}")publicStringdriverClassName;@Value("${jdbc.url}")publicStringurl;@Value("${jdbc.username}")publicStringusername;@Value("${jdbc.password}")publicStringpassword;@BeanpublicDataSourcedataSource(){DruidDataSourcedataSource=newDruidDataSource();dataSource.setDriverClassName(driverClassName);dataSource.setUrl(url);dataSource.setUsername(username);dataSource.setPassword(password);returndataSource;}@Bean//把事务管理器交给Spring管理publicDataSourceTransactionManagerdataSourceTransactionManager(DataSourcedataSource){DataSourceTransactionManagertransactionManager=newDataSourceTransactionManager();transactionManager.setDataSource(dataSource);returntransactionManager;}}第三步、在SpringConfig使用注解开启事务@Configuration@ComponentScan({"cn.bigdataboy"})@PropertySource({"classpath:jdbc.properties"})@Import({MyBatisConfig.class,JdbcConfig.class})@EnableTransactionManagement//开启事务管理器publicclassSpringConfig{}测试注意默认状态下并不是所有的异常都会回滚,可以通过事务属性进行控制事务角色在上述案例中,小事务一和二(事务协调员)会被加入到大的事务(事务管理员),由事务管理员统一管理事务管理员:在Spring中通常指开启事务的方法事务协调员:在Spring中通常指数据层方法,也可以是业务层方法事务的属性事务的属性能使事务管理员对事务协调员精细化的管理属性作用实例readOnly设置是否为只读事务readOnly=true只读事务timeout设置事务超时时间timeout=-1(永不超时)rollbackFor设置事务回滚异常(class)rollbackFor={NullPointerException.class}rollbackForClassName设置事务回滚异常(String)同上,只是参数为字符串noRollbackFor设置事务不回滚异常(class)noRollbackFor={NullPointerException.class}noRollbackForClassName设置事务不回滚异常(String)同上,只是参数为字符串propagation事务传播见下面事务传播默认情况下,发送错误时,子事务全部都要回滚,那有一些事务是不需要回滚(记录日志到数据库),这也是需要实现的,子事务可以控制自己是否需要主事务控制。publicinterfaceAccountLogService{@Transactional(propagation=Propagation.REQUIRES_NEW)//该注解开启事务publicvoidadd(Stringout,Stringin,Doublemoney);}propagation参数说明(T代表事务)传播属性事务管理员事务协调员REQUIRED(默认)开启T/无加入T/新建T2REQUIRES_NEW开启T/无新建T2/新建T2SUPPORTS开启T/无加入T/无NOT_SUPPORTED开启T/无无/无MANDATORY开启T/无加入T/ERRORNEVER开启T/无ERROT/无NESTED开启T/无设置savePoint,一但事务回滚,事务将回滚到savaPoint处,交由客户端提交/回滚案例代码:https://pan.bigdataboy.cn/s/QgVFn
新博客:https://blog.bigdataboy.cn/article/452.html说明项目地址:https://github.com/junit-team/junit5添加maven依赖<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.10.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>5.2.10.RELEASE</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency></dependencies>创建测试类@RunWith(SpringJUnit4ClassRunner.class)//告诉Junit执行的Spring测试类@ContextConfiguration(classes=SpringConfig.class)//注入配置类publicclassUserDaoTest{@AutowiredprivateUserDaouserDao;@TestpublicvoidtestGetUser(){userDao.getUser();}}测试需要测试什么类,直接注入案例代码:https://pan.bigdataboy.cn/s/eXKC4
新博客:https://blog.bigdataboy.cn/article/450.htmlMyBatis说明mybatis-spring官网:https://mybatis.org/spring/zh/index.html介绍:MyBatis-Spring会帮助你将MyBatis代码无缝地整合到Spring中。它将允许MyBatis参与到Spring的事务管理之中,创建映射器mapper和SqlSession并注入到bean中,以及将Mybatis的异常转换为Spring的DataAccessException。添加Jar依赖pom.xml文件添加,注意版本问题<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.10.RELEASE</version></dependency><!--springjdbc操作--><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.3.2</version></dependency><!--阿里巴巴数据源--><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.24</version></dependency><!--mybatis--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.6</version></dependency><!--mybatisspring结合--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>2.0.7</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.8</version></dependency></dependencies>添加配置类和配置文件数据库Sql文件SETNAMESutf8mb4;SETFOREIGN_KEY_CHECKS=0;--------------------------------Tablestructureforaccount------------------------------DROPTABLEIFEXISTS`account`;CREATETABLE`account`(`id`int(11)NOTNULLAUTO_INCREMENT,`users`varchar(255)CHARACTERSETutf8mb4COLLATEutf8mb4_binNULLDEFAULTNULL,`money`double(255,0)NULLDEFAULTNULL,PRIMARYKEY(`id`)USINGBTREE)ENGINE=InnoDBAUTO_INCREMENT=3CHARACTERSET=utf8mb4COLLATE=utf8mb4_binROW_FORMAT=Compact;--------------------------------Recordsofaccount------------------------------INSERTINTO`account`VALUES(1,'a',100);INSERTINTO`account`VALUES(2,'b',200);SETFOREIGN_KEY_CHECKS=1;jdbc.properties在resources文件夹下jdbc.driver=com.mysql.jdbc.Driverjdbc.url=jdbc:mysql://127.0.0.1:3306/spring_dbjdbc.username=rootjdbc.password=rootJdbcConfig配置类Spring第三方Bean管理@ConfigurationpublicclassJdbcConfig{@Value("${jdbc.driver}")publicStringdriverClassName;@Value("${jdbc.url}")publicStringurl;@Value("${jdbc.username}")publicStringusername;@Value("${jdbc.password}")publicStringpassword;@BeanpublicDataSourcedataSource(){DruidDataSourcedataSource=newDruidDataSource();dataSource.setDriverClassName(driverClassName);dataSource.setUrl(url);dataSource.setUsername(username);dataSource.setPassword(password);returndataSource;}}MyBatisConfig配置类Spring第三方Bean管理@ConfigurationpublicclassMyBatisConfig{@Bean//连接工厂BeanpublicSqlSessionFactoryBeansqlSessionFactory(DataSourcedataSource)throwsException{SqlSessionFactoryBeanfactoryBean=newSqlSessionFactoryBean();factoryBean.setDataSource(dataSource);returnfactoryBean;}@Bean//MapperBeanpublicMapperScannerConfigurermapperScannerConfigurer(){MapperScannerConfigurermapperScannerConfigurer=newMapperScannerConfigurer();mapperScannerConfigurer.setBasePackage("cn.bigdataboy.dao");//设置Mapper映射的包,扫描Mapper注解,已经转化成Mapper,相对于以前的Mapper配置returnmapperScannerConfigurer;}}Spring配置类@Configuration@ComponentScan({"cn.bigdataboy"})@PropertySource({"classpath:jdbc.properties"})@Import({MyBatisConfig.class,JdbcConfig.class})//导入配置publicclassSpringConfig{}添加实体类实体类,就是查询结果的映射类,在domain文件夹下publicclassAccount{privateintid;privateStringusers;privateDoublemoney;@OverridepublicStringtoString(){return"Account{"+"id="+id+",users='"+users+'\''+",money="+money+'}';}}添加dao层dao层是数据处理,结合Mybatis后,就是原来的Mapper配置@MapperpublicinterfaceAccountDao{@Select("SELECT*FROMaccountWHEREid=#{userId}")AccountgetUserById(@Param("userId")intuserId);@Select("SELECT*FROMaccount")List<Account>getAllUser();}添加service层业务处理层,实现两个功能,按id查询和查询全部@ServicepublicclassAccountServiceImplimplementsAccountService{@AutowiredprivateAccountDaoaccountDao;@OverridepublicAccountgetUserById(intid){returnaccountDao.getUserById(id);}@OverridepublicList<Account>getAllUser(){returnaccountDao.getAllUser();}}测试publicclassApp{publicstaticvoidmain(String[]args){AnnotationConfigApplicationContextcontext=newAnnotationConfigApplicationContext(SpringConfig.class);AccountServiceaccountService=context.getBean(AccountService.class);Accountaccount=accountService.getUserById(1);System.out.println(account);System.out.println(accountService.getAllUser());}}案例代码:https://pan.bigdataboy.cn/s/mXnux
新博客:https://blog.bigdataboy.cn/article/449.html概念AOP(面向切面编程)是一种编程思想,Python的装饰器有这种思想,逆向中的Hook技术也有这种思想在不改变原来方法的情况下,增加功能,只是在不同框架,不同语言下,实现方式和写法不一样实现思路:获取原来函数-执行顺序-参数&返回值增强方法,那肯定会让原来的方法肯执行,所以得需要获取原来方法既然还要增强方法,那得考虑增强的逻辑什么时候执行吧,是在原来的函数执行前,还是执行后吧最后是参数和返回值的问题,既然是增强,那我的参数和返回值要符合原来的函数的规则Spring的实现方式在pom.xml添加依赖<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.10.RELEASE</version></dependency><dependency><!--用来解析切入点表达式--><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.4</version></dependency></dependencies>编写增强方法类,这个类还是需要按照Spring的规则变成交给容器管理的Bean@Component//记得BeanpublicclassAdvice{}获取原来的方法,Spring使用了一种用表达式匹配的方式,后面详细介绍@Component//记得BeanpublicclassAdvice{@Pointcut("execution(voidcn.bigdataboy.dao.NameDao.getById())")//切入点表达式privatevoidpt(){}//可以理解为代表原方法}编写增强逻辑的方法,并设定执行的时机,有五种,后面详细介绍@Component//记得BeanpublicclassAdvice{@Pointcut("execution(voidcn.bigdataboy.dao.NameDao.getById())")privatevoidpt(){}//可以理解为代表原方法@Before("pt()")//增强方法执行时机,有五种publicvoidmethod(){//增强的方法在这里System.out.println("当前执行时间:"+System.currentTimeMillis());}}添加注解,告诉Spring这是AOP的类@Component//记得Bean@Aspect//添加注解publicclassAdvice{@Pointcut("execution(voidcn.bigdataboy.dao.NameDao.getById())")privatevoidpt(){}//可以理解为代表原方法@Before("pt()")//增强方法执行时机,有五种,参数是原方法publicvoidmethod(){//增强的方法在这里System.out.println("当前执行时间:"+System.currentTimeMillis());}}最后在配置类添加注解,开启AOP功能@Configuration@ComponentScan({"cn.bigdataboy.dao","cn.bigdataboy.aop"})//注意Bean不要漏了@EnableAspectJAutoProxy//开启aop代理publicclassSpringConfig{}五种执行时机@Before("")在原函数执行前执行@Before("pt()")//之前执行publicvoidmethodBefore(){//增强的方法在这里System.out.println("@Beforerunning...");}@After("")在原函数执行后执行,如果原函数报错也会执行@After("pt()")//之后执行,如果原方法报错,也会执行publicvoidmethodAfter(){//增强的方法在这里System.out.println("@Afterrunning...");}@Around("")重点常用环绕执行,所以它有点特殊,有一个参数,包含原方法和它的各种信息,相对于执行锚点,能控制在增强函数的什么位置执行@Around("pt()")//环绕执行publicvoidmethodAround(ProceedingJoinPointpjp)throwsThrowable{//增强的方法在这里System.out.println("当前执行时间@Around:"+System.currentTimeMillis());pjp.proceed();//相对于传入锚点,执行位置System.out.println("当前执行时间@Around:"+System.currentTimeMillis());}@AfterReturning("")原方法成功执行时触发,原方法报错,则不会执行@AfterReturning("pt()")//在原方法正常执行后才会触发,也就说入原方法报错,就不会触发了publicvoidmethodAfterReturning(){//增强的方法在这里System.out.println("@AfterReturningrunning...");}@AfterThrowing("")在原方法报错触发@AfterThrowing("pt()")//在原方法报错触发publicvoidmethodAfterThrowing(){//增强的方法在这里System.out.println("@AfterThrowingrunning...");}切入点表达式切入点表达式,是Spring用来表达增强方法对哪些方法生效的式子@Pointcut("execution(voidcn.bigdataboy.dao.NameDao.getById())")privatevoidpt(){}//可以理解为代表原方法格式:动作关键字(访问修饰符返回值类型包名.类/接口名.方法名(参数)异常名)(有些是可以省略的)动作关键字:几乎都是execution()访问修饰符:public、private...可以省略返回值:是什么写什么异常名:方法中定义的抛出异常,可以省略切入点表达式通配快速描述*:单个独立的任意符号,可以独立出现,可以作为前缀或者后缀的匹配符出现execution(*cn.bigdataboy.dao.*Dao.getBy*())..:多个连续的任意符号,可以独立出现,常用于简化包名和参数出现execution(*cn..NameDao.getById(..))+:专用于匹配子类型execution(*cn.bigdataboy.dao.NameDao+.*())参数&返回值处理既然是增强方法,那参数和返回值就要处理,那同时,如果方法异常,那异常信息也要处理。都是使用形参获取的。参数处理@Before、@After、@AfterReturning、@AfterThrowing都是传入JoinPoint对象执行getArgs()获取原始方法参数数组JoinPoint对象包含大量信息对于@Around是传入ProceedingJoinPoint对象执行getArgs()获取原始方法参数数组返回值处理对于返回值,只有@Around、@AfterReturning有,其他的不涉及返回值@Around方式设计参数和返回值,所以为了规范,返回值可以是Object@Around("pt()")//环绕执行publicObjectmethodAround(ProceedingJoinPointpjp)throwsThrowable{//增强的方法在这里System.out.println("@Aroundrunningargs:"+Arrays.toString(pjp.getArgs()));Objectproceed=pjp.proceed(pjp.getArgs());//相对于锚点,执行位置System.out.println("@Aroundrunningres:"+proceed);returnproceed;}@AfterReturning获取返回值有点特殊,需要指定注解的returning参数@AfterReturning(value="pt()",returning="ret")//在原方法正常执行后才会触发,也就说入原方法报错,就不会触发了publicvoidmethodAfterReturning(Objectret){//增强的方法在这里System.out.println("@AfterReturningrunningres:"+ret);}案例代码:https://pan.bigdataboy.cn/s/Lglh5
新博客:https://blog.bigdataboy.cn/article/448.html管理第三方Bean第三方Bean没有办法写给它注解,所以就只能添加,Spring的处理是在配置类中写一个函数,该函数使用@Beam注解第三方Bean配置类第三方Bean的配置类,建议单独文件编写,这样不冗余,全部写一个配置类,会变得一大坨importcom.alibaba.druid.pool.DruidDataSource;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importjavax.sql.DataSource;@ConfigurationpublicclassJdbcConfig{@Bean//表示返回一个Bean,也可以指定id->@Bean("dataSource")publicDataSourcedataSource(){//参数先空着DruidDataSourcedataSource=newDruidDataSource();dataSource.setDriverClassName("");dataSource.setUrl("");dataSource.setUsername("");dataSource.setPassword("");returndataSource;}}在主配置类导入第三方配置类@Configuration@ComponentScan({"cn.bigdataboy.dao"})@Import({JdbcConfig.class})//导入publicclassSpringConfig{}获取第三方Bean第三方Bean的注入资源上面的例子,JDBC的链接还空着,所以我们需要为其注入参数注入简单类型注入方式与注入自己的Bean一样,使用成员属性添加@Value()注解importcn.bigdataboy.dao.NameDao;importcom.alibaba.druid.pool.DruidDataSource;importorg.springframework.beans.factory.annotation.Value;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importjavax.sql.DataSource;@ConfigurationpublicclassJdbcConfig{@Value("${jdbc.driver}")publicStringdriverClassName;@Value("${jdbc.url}")publicStringurl;@Value("${jdbc.username}")publicStringusername;@Value("${jdbc.password}")publicStringpassword;@Bean//表示返回一个Bean,也可以指定id->@Bean("dataSource")publicDataSourcedataSource(){System.out.println(this.driverClassName);System.out.println(this.url);DruidDataSourcedataSource=newDruidDataSource();dataSource.setDriverClassName(this.driverClassName);dataSource.setUrl(this.url);dataSource.setUsername(this.username);dataSource.setPassword(this.password);returndataSource;}}注入引入类型这里注入引入类型,有点不一样,直接添加成方法参数就好,因为Spring容器中已经存在相应的Bean,那么它也就能自己找到,因此也容易想到它是使用类型方式找的importcn.bigdataboy.dao.NameDao;importcom.alibaba.druid.pool.DruidDataSource;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importjavax.sql.DataSource;@ConfigurationpublicclassJdbcConfig{@Bean//表示返回一个Bean,也可以指定id->@Bean("dataSource")publicDataSourcedataSource(NameDaonameDao){//添加成参数System.out.println(nameDao);//打印一下,表示注入成功DruidDataSourcedataSource=newDruidDataSource();//相应配置returndataSource;}}案例代码:https://pan.bigdataboy.cn/s/NO5sp
新博客:https://blog.bigdataboy.cn/article/447.html说明Properties文件是Java中很常用的一种配置文件,文件后缀为.properties,属文本文件,文件的内容格式是键=值的格式,可以用#作为注释,Java编程中用到的地方很多,运用配置文件,可以便于Java深层次的解耦。注解加载properties文件在配置类添加注解PropertySourceimportorg.springframework.context.annotation.ComponentScan;importorg.springframework.context.annotation.Configuration;importorg.springframework.context.annotation.PropertySource;@Configuration@ComponentScan({"cn.bigdataboy.dao","cn.bigdataboy.service"})@PropertySource({"classpath:jdbc.properties"})//可以添加多个配置文件不允许通配符//@PropertySource({"jdbc.properties"})//可以添加多个配置文件不允许通配符publicclassSpringConfig{}通过简单类型注入的方式,可以把参数注入到Bean中@Service//业务层BeanpublicclassNameServiceImplimplementsNameService{@Value("${jdbc.username}")//占位符privateStringusername;publicvoidsave(){System.out.println(this.username+"servicesave...");}}案例代码:https://pan.bigdataboy.cn/s/qB6C6
新博客:https://blog.bigdataboy.cn/article/446.html依赖注入注解方式的依赖注入,是自动装配实现,按照类型注入的,添加@Autowired就行,还可以添加@Qualifier("id")注解指定id注入引入类型注入自动装配基于反射设计创建对象并暴力反射对象属性为私有属性初始化数据,因此无需提供setter方法自动装配建议使用无参的构造方法创建对象(默认),如果不提供对应构造方法,请提供唯一的构造方法importcn.bigdataboy.dao.NameDao;importcn.bigdataboy.service.NameService;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.beans.factory.annotation.Qualifier;importorg.springframework.beans.factory.annotation.Value;importorg.springframework.stereotype.Service;@Service//业务层BeanpublicclassNameServiceImplimplementsNameService{@Autowired//@Qualifier("")//当自动装配不OK时,可以使用该注解进行指定id加载BeanprivateNameDaonameDao;@Value("bigdataboy")privateStringname;publicvoidsave(){System.out.println("servicesave...");nameDao.getName();}}基础类型注入基础类型的注入,使用@Value注解,但在实际中不会这样使用,而是用来注入,第三方配置文件的配置见文章:@Value("bigdataboy")privateStringname;案例代码:https://pan.bigdataboy.cn/s/DrKS6
新博客:https://blog.bigdataboy.cn/article/445.htmlBean作用范围直接一个直接就搞定@Scope("singleton")importcn.bigdataboy.dao.NameDao;importorg.springframework.context.annotation.Scope;importorg.springframework.stereotype.Repository;importjavax.annotation.PostConstruct;importjavax.annotation.PreDestroy;@Repository@Scope("singleton")//prototype/singleton(默认)publicclassNameDaoImplimplementsNameDao{publicvoidgetName(){System.out.println("getName:bigdataboy");}}生命周期直接一个直接就搞定,@PostConstruct(初始化之后),@PreDestroy(在销毁前)importcn.bigdataboy.dao.NameDao;importorg.springframework.context.annotation.Scope;importorg.springframework.stereotype.Repository;importjavax.annotation.PostConstruct;importjavax.annotation.PreDestroy;@RepositorypublicclassNameDaoImplimplementsNameDao{publicvoidgetName(){System.out.println("getName:bigdataboy");}@PostConstruct//初始化之后publicvoidinit(){System.out.println("initrunning...");}@PreDestroy//在销毁前publicvoiddestroy(){System.out.println("destroyrunning...");}}案例代码:https://pan.bigdataboy.cn/s/pvJcR
新博客:https://blog.bigdataboy.cn/article/444.html注解开发配置文件的作用降低,只需要完成扫描器的定义就行,类上添加一个注解,就表示该类是容器管理的Bean类添加注解importcn.bigdataboy.service.NameService;importorg.springframework.stereotype.Component;@Component("nameService")//参数就是idpublicclassNameServiceImplimplementsNameService{publicvoidsave(){System.out.println("servicesave...");}}类注解的官方推荐使用importorg.springframework.stereotype.Controller;importorg.springframework.stereotype.Repository;importorg.springframework.stereotype.Service;importorg.springframework.stereotype.Component;@Controller//表现层@Service//业务层@Repository//数据层@Component("nameService")//其他层配置添加扫描器<?xmlversion="1.0"encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:context="http://www.springframework.org/schema/context"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!--定义扫描器上面的命名空间要完整,idea自动的生成的不完整--><context:component-scanbase-package="cn.bigdataboy"/></beans>纯注解开发不再需要配置文件,所以也很容易想到,配置文件转变成配置类,同时也就能想到,在初始化容器时,传入的也就不是配置文件,而是配置类了配置类格式importorg.springframework.context.annotation.ComponentScan;importorg.springframework.context.annotation.Configuration;@Configuration//表示配置类@ComponentScan({"cn.bigdataboy.dao","cn.bigdataboy.service"})//扫描器定义多个路径,可以通配,建议准确一点,毕竟有些类不建议Bean化publicclassSpringConfig{}使用importcn.bigdataboy.config.SpringConfig;importcn.bigdataboy.dao.NameDao;importcn.bigdataboy.service.NameService;importorg.springframework.context.annotation.AnnotationConfigApplicationContext;publicclassAppForAnnotation{publicstaticvoidmain(String[]args){//加载配置类AnnotationConfigApplicationContextcontext=newAnnotationConfigApplicationContext(SpringConfig.class);//从容器获取对象NameServicenameService=(NameService)context.getBean("nameService");NameDaonameDao=context.getBean("nameDao",NameDao.class);System.out.println(nameService);System.out.println(nameDao);}}案例代码:https://pan.bigdataboy.cn/s/y4jie
新博客:https://blog.bigdataboy.cn/article/443.htmlsetter注入setter注入方式,就是Spring利用对象的set方法,结合书写配置的规则进行注入对象的格式添加set方法publicclassNameServiceImplimplementsNameService{privateNameDaonameDao;publicStringname;//简单类型注入publicvoidsetName(Stringname){this.name=name;}//引用类型注入publicvoidsetNameDao(NameDaonameDao){this.nameDao=nameDao;}publicvoidsave(){System.out.println(this.name+"servicesave...");nameDao.getName();}}配置文件<!--管理对象--><beanid="nameDao"class="cn.bigdataboy.dao.impl.NameDaoImpl"/><beanid="nameService"class="cn.bigdataboy.service.impl.NameServiceImpl"><!--引用类型写法--><propertyname="nameDao"ref="nameDao"/><!--简单类型写法--><propertyname="name"value="bigdataboy"/></bean>例子代码:https://pan.bigdataboy.cn/s/n8RFW构造器注入构造器的输入,不外乎需要注意参数是怎么注入的对象格式publicclassNameServiceImplimplementsNameService{publicNameDaonameDao;publicStringname;//常规写法publicNameServiceImpl(NameDaonameDao,Stringname){this.nameDao=nameDao;this.name=name;}publicvoidsave(){System.out.println(this.name+"servicesave...");nameDao.getName();}}配置文件构造器的注入,因为解耦,所以有几种写法<!--管理对象--><beanid="nameDao"class="cn.bigdataboy.dao.impl.NameDaoImpl"/><beanid="nameService"class="cn.bigdataboy.service.impl.NameServiceImpl"><!--这里的name是参数名称,这样还是耦合,所以还有其他写法--><constructor-argname="nameDao"ref="nameDao"/><constructor-argname="name"value="bigdataboy"/><!--通过类型匹配--><!--<constructor-argtype="cn.bigdataboy.dao.NameDao"ref="nameDao"/>--><!--<constructor-argtype="java.lang.String"value="bigdataboy"/>--><!--通过索引(参数位置)--><!--<constructor-argindex="0"ref="nameDao"/>--><!--<constructor-argindex="1"value="bigdataboy"/>--></bean>例子代码:https://pan.bigdataboy.cn/s/XmVTK依赖自动装配要实现自动,那肯定是需要写法规范,不然框架也不知道你要怎么装自动装配是利用set方法实现的。自动装配只能对引用类型进行装配,不能对简单类型进行装配。自动和手动配置能搭配使用,自动装配的优先级小于手动。五种自动装配模式byName对象里的set方法的名字,需要与配置文件的Beanid相对应,不然会找不到。byType这个模式就不需要id和set对应了例子代码:https://pan.bigdataboy.cn/s/254HZ集合类型注入集合类型的注入只是在配置文件的写法有区别,会有多个原素对象的格式publicclassNameServiceImplimplementsNameService{privateint[]array;privateList<String>list;privateSet<String>set;privateMap<String,String>map;privatePropertiesproperties;publicvoidsetArray(int[]array){this.array=array;}publicvoidsetList(List<String>list){this.list=list;}publicvoidsetSet(Set<String>set){this.set=set;}publicvoidsetMap(Map<String,String>map){this.map=map;}publicvoidsetProperties(Propertiesproperties){this.properties=properties;}@Overridepublicvoidsave(){System.out.println("array:"+Arrays.toString(this.array));System.out.println("list:"+this.list);System.out.println("set:"+this.set);System.out.println("map:"+this.map);System.out.println("properties:"+this.properties);}}配置文件格式还是简单<beanid="nameService"class="cn.bigdataboy.service.impl.NameServiceImpl"><propertyname="array"><array><value>100</value><value>200</value></array></property><propertyname="list"><list><value>100</value><value>200</value></list></property><propertyname="set"><set><value>100</value><value>200</value></set></property><propertyname="map"><map><entrykey="name"value="bigdataboy"></entry></map></property><propertyname="properties"><props><!--这个有点特殊--><propkey="name">bigdataboy</prop></props></property></bean>例子代码:https://pan.bigdataboy.cn/s/Y4jSb
新博客:https://blog.bigdataboy.cn/article/442.htmlBean基础配置格式<?xmlversion="1.0"encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!--管理对象--><beanid="nameDao"name="daodao2,dao3"class="cn.bigdataboy.dao.impl.NameDaoImpl"/></beans>属性列表属性描述idBean唯一标识nameBean的别名,多个由逗号、分号隔开class该Bean的类路径scope作用范围,用于规定获取的Bean是否是单例的(默认是singleton单例)scope属性singleton单例:也就是使用的是同一个对象prototype非单例:常用于对象内部是有属性保存状态的,该对象运行一次,内部的属性需要给下次的执行。Bean实例化使用构造方法实例化Bean的实例化,也是从构造方法开始,容器内部是使用反射机制完成的<beanid="nameDao"class="cn.bigdataboy.dao.impl.NameDaoImpl"scope="singleton"/>这里有个小问题,如果是非单例模式,会输出两次构造函数的打印使用工厂函数实例化需要继承FactoryBean,重写getObjectgetObjectType,isSingleton需要再写packagecn.bigdataboy.factory;importcn.bigdataboy.dao.NameDao;importcn.bigdataboy.dao.impl.NameDaoImpl;importorg.springframework.beans.factory.FactoryBean;publicclassNameDaoFactoryBeanimplementsFactoryBean<NameDao>{@OverridepublicNameDaogetObject()throwsException{returnnewNameDaoImpl();}@OverridepublicClass<?>getObjectType(){returnNameDaoImpl.class;}@OverridepublicbooleanisSingleton(){returntrue;}}配置文件只需要这样写<!--使用FactoryBean方式实例化Bean--><beanid="nameDao"class="cn.bigdataboy.factory.NameDaoFactoryBean"></bean>Bean生命周期生命周期其实很好理解,就是创建,销毁这样一个过程,既然有这样一个概念,那就可以控制相应阶段做不同的事。Spring的实现方式还是使用配置属性,指定相应方法初始化方法和销毁方法importcn.bigdataboy.dao.NameDao;importcn.bigdataboy.service.impl.NameServiceImpl;publicclassNameDaoImplimplementsNameDao{publicNameDaoImpl(){System.out.println("NameDaoImplconstructorrunning...");}publicvoidgetName(){System.out.println("getName:bigdataboy");}publicvoidinit(){//初始化方法System.out.println("namedaoinit...");}publicvoiddestory(){//销毁方法System.out.println("namedaodestory...");}}配置文件,指定相应方法<beanid="nameDao"class="cn.bigdataboy.dao.impl.NameDaoImpl"init-method="init"destroy-method="destory"/>销毁方法,需要修改成ClassPathXmlApplicationContext接口才有,不然是不会调用销毁的。
新博客:https://blog.bigdataboy.cn/article/441.htmlIoc/Ioc容器/DI需要解决的问题:解耦,不手动new对象,而是容器提供对象。使用new对象会产生高耦合,在改动代码后,必须重新编译、打包、部署Ioc(控制反转)使用对象时,有主动new产生对象转变成外部提供对象。Ioc容器外部提供对象的容器就叫Ioc容器,对象将由Ioc容器管理对象,能够管理对象的创建、初始化等一系列事情,创建后的对象被称为BeanDI(依赖注入)在容器中建立Bean与Bean之间的依赖关系,这个过程叫做依赖注入例子解决疑问:怎么实现的不用new:容器管理容器怎么知道管理什么对象:使用spring规定的xml配置文件DI怎么实现的依赖注入:配置项关联例子使用5.2.10.RELEASE版本<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.10.RELEASE</version></dependency></dependencies>创建spring配置(需要加载maven依赖后,才会有这个选项)在spring配置配置文件中添加beanid:Bean的唯一标识name:Bean的别名,多个由空格逗号分割class:后面是需要容器管理对象的路径<?xmlversion="1.0"encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!--管理对象--><beanid="nameDao"class="cn.bigdataboy.dao.impl.NameDaoImpl"/></beans>使用,不用new体现在,使用nameDao对象不是new出来的packagecn.bigdataboy;importcn.bigdataboy.dao.NameDao;importorg.springframework.context.ApplicationContext;importorg.springframework.context.support.ClassPathXmlApplicationContext;publicclassApp1{publicstaticvoidmain(String[]args){//传入配置文件路径不会这么使用,仅举例ApplicationContextcontext=newClassPathXmlApplicationContext("applicationContext.xml");//从容器获取对象NameDaonameDao=(NameDao)context.getBean("nameDao");nameDao.getName();}}业务层的处理需要依赖数据层的对象,需要使用DI处理它们的依赖配置添加属性标签并建立关联<!--管理对象--><beanid="nameDao"class="cn.bigdataboy.dao.impl.NameDaoImpl"/><beanid="NameService"class="cn.bigdataboy.service.impl.NameServiceImpl"><!--配置NameService类中依赖的beanname是NameServiceImpl类中的变量名,ref才是bean的id关联--><propertyname="nameDao"ref="nameDao"></property></bean>业务层的类也需要开启一个接口方法,方便容器进行设置publicclassNameServiceImplimplementsNameService{/***原来业务层需要new数据层进行操作*privateNameDaonameDao=newNameDaoImpl();*/privateNameDaonameDao;publicvoidsave(){System.out.println("nameservicesave...");nameDao.getName();}//相对于开个接口给容器,好能能进行设置publicvoidsetNameDao(NameDaonameDao){this.nameDao=nameDao;}}[]()相关代码:https://pan.bigdataboy.cn/s/bDrs0