【快速学习系列】Spring理解,IOC、DI、AOP的使用和代码示例及spring扩展(bean作用域、自动装配类型和拆分策略)
创始人
2024-04-24 06:00:16
0

【快速学习系列】Spring理解,IOC、DI、AOP的使用和代码示例及spring扩展(bean作用域、自动装配类型和拆分策略)

Spring概述

  • Spring设计理念
    • Spring是面向Bean的编程
  • Spring三大核心容器:
    • Beans,Core,Context
  • Spring 两大核心技术
    • 控制反转(IoC:Inversion of Control ) /依赖
      注入(DI:Dependency Injection )
    • 面向切面编程(AOP:Aspect Oriented Programming)

IOC(控制反转)和 DI 依赖注入

IOC(控制反转)

  • 将组件对象的控制权从代码本身转移到外部容器
    • 通俗理解:
      • 定义接口在代码中,配置文件为实现new接口的过程( 把new对象放到了配置文件里 )
      • 控制权:new的过程
      • 外部容器:外部配置文件(xml、yml…)

组件化的思想:分离关注点,使用接口,不再关注实现

DI 依赖注入

  • 将组件的构建使用分开
    • 通俗理解:
      • 在xml中给对象属性赋值
      • 构建:进行自动装配的dao层接口
      • 使用:dao层接口的实现方法

图解

请添加图片描述

使用

引入jar包

4.0.2.RELEASE

org.springframeworkspring-test${spring.version}

org.springframeworkspring-core${spring.version}

org.springframeworkspring-oxm${spring.version}

org.springframeworkspring-tx${spring.version}

org.springframeworkspring-jdbc${spring.version}

org.springframeworkspring-aop${spring.version}

org.springframeworkspring-context${spring.version}

org.springframeworkspring-context-support${spring.version}

org.springframeworkspring-expression${spring.version}

org.springframeworkspring-orm${spring.version}

org.springframeworkspring-web${spring.version}

org.springframeworkspring-webmvc${spring.version}

参数注入
示例

1、用spring打印Hello Spring!!!

新建一个HelloWord.java类

package com.r.test;import lombok.Setter;/**** @Author Tuerlechat,* @Date 2022/10/28*/
@Setter     //被注入的属性一定要有setter方法,否则Spring注入不进去呀也
public class HelloWorld {private String message;public void show() {System.out.println(message);}
}

resources根目录下新建一个Spring Config类型文件(或者xml文件直接粘头部代码)为spring.xml

spring.xml



测试类HelloWorldTest.java

package com.r.test;import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;/**** @Author Tuerlechat,* @Date 2022/10/28*/
public class HelloWorldTest {@Testpublic void show() {//读取spring配置文件ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");//获取spring配置文件中的beanHelloWorld hw = (HelloWorld)ac.getBean("helloWorld");//调用被注入的类中的方法hw.show();}
}

2、墨盒打印机

墨盒接口Ink:

/*** 墨盒接口。*/
public interface Ink {/*** 定义打印采用的颜色的方法。* * @param r*            红色值* @param g*            绿色值* @param b*            蓝色值* @return 返回打印采用的颜色*/public String getColor(int r, int g, int b);
}

纸张接口Paper:

/*** 纸张接口。*/
public interface Paper {public static final String newline = "\r\n";/*** 输出一个字符到纸张。*/public void putInChar(char c);/*** 得到输出到纸张上的内容。*/public String getContent();
}

彩色墨盒ColorInk类:

/*** 彩色墨盒。ColorInk实现Ink接口。*/
public class ColorInk implements Ink {// 打印采用彩色public String getColor(int r, int g, int b) {Color color = new Color(r, g, b);return "#" + Integer.toHexString(color.getRGB()).substring(2);}
}

灰色墨盒GreyInk类:

/*** 灰色墨盒。GreyInk实现Ink接口。*/
public class GreyInk implements Ink {// 打印采用灰色public String getColor(int r, int g, int b) {int c = (r + g + b) / 3;Color color = new Color(c, c, c);return "#" + Integer.toHexString(color.getRGB()).substring(2);}
}

打印文本纸张TextPaper类:

/*** 文本打印纸张实现。TextPaper实现Paper接口。*/
public class TextPaper implements Paper {// 每行字符数private int charPerLine = 16;// 每页行数private int linePerPage = 5;// 纸张中内容private String content = "";// 当前横向位置,从0到charPerLine-1private int posX = 0;// 当前行数,从0到linePerPage-1private int posY = 0;// 当前页数private int posP = 1;public String getContent() {String ret = this.content;// 补齐本页空行,并显示页码if (!(posX == 0 && posY == 0)) {int count = linePerPage - posY;for (int i = 0; i < count; ++i) {ret += Paper.newline;}ret += "== 第" + posP + "页 ==";}return ret;}public void putInChar(char c) {content += c;++posX;// 判断是否换行if (posX == charPerLine) {content += Paper.newline;posX = 0;++posY;}// 判断是否翻页if (posY == linePerPage) {content += "== 第" + posP + "页 ==";content += Paper.newline + Paper.newline;posY = 0;++posP;}}// setter方法,用于属性注入public void setCharPerLine(int charPerLine) {this.charPerLine = charPerLine;}// setter方法,用于属性注入public void setLinePerPage(int linePerPage) {this.linePerPage = linePerPage;}
}

打印机程序Printer类:

/*** 打印机程序。*/
public class Printer {// 面向接口编程,而不是具体的实现类private Ink ink = null;// 面向接口编程,而不是具体的实现类private Paper paper = null;/*** 设值注入所需的setter方法。* * @param ink*            传入墨盒参数*/public void setInk(Ink ink) {this.ink = ink;}/*** 设值注入所需的setter方法。* * @param paper*            传入纸张参数*/public void setPaper(Paper paper) {this.paper = paper;}/*** 打印机打印方法。* * @param str*            传入打印内容*/public void print(String str) {// 输出颜色标记System.out.println("使用" + ink.getColor(255, 200, 0) + "颜色打印:\n");// 逐字符输出到纸张for (int i = 0; i < str.length(); ++i) {paper.putInChar(str.charAt(i));}// 将纸张的内容输出System.out.print(paper.getContent());}
}

spring.xml




测试类PrinterTest:

package com.r.test;import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;/**** @Author Tuerlechat,* @Date 2022/10/28*/
public class PrinterTest {@Testpublic void printer() {//读取spring配置文件ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");//获取spring配置文件中的beanPrinter printer = (Printer) ac.getBean("printer");//调用被注入的类中的方法printer.print("“拥有梦想是一件很棒很幸运的事情,如果你能享受为梦想奋斗,\n" +"享受实现梦想的过程,那没有什么比这更好的事情了。\n" +"当你享受其中你就会投入更多,当你享受其中,\n" +"所有的事都会相辅相成、相互促进”\n" +"“꿈을갖는것은멋지고행운이다.\n" +"꿈을이루기위해분투하는과정을즐길수있다면이보다더좋은것은없다.\n" +"당신이그것을즐길때당신은더많은것을투자할것입니다.\n" +"당신이그것을즐길때,모든것이상호보완적이고상호촉진될” -박채영");}
}
构造函数注入 (constructor-arg)
示例

构造注入新增user

dao层接口

/*** @Author Tuerlechat,* @Date 2022/10/31*/
public interface UserDao {/*** 构造注入新增user* @param user* @return*/public int addNewUser(User user);}

dao层实现

/*** @Author Tuerlechat,* @Date 2022/10/31*/
public class UserDaoImpl implements UserDao {@Overridepublic int addNewUser(User user) {System.out.println("新增用户addNewUser。");return 0;}}

service层接口

/*** @Author Tuerlechat,* @Date 2022/10/31*/
public interface UserService {public int addNewUser(User user);}

service层实现

/*** @Author Tuerlechat,* @Date 2022/10/31*/
@AllArgsConstructor    //有参构造
@NoArgsConstructor     //无参构造
@Setter
public class UserServiceImpl implements UserService {private UserDao userDao;    //构造注入@Overridepublic int addNewUser(User user) {return userDao.addNewUser(user);}}

配置文件spring.xml





测试类

/*** 测试类* @Author Tuerlechat,* @Date 2022/10/31*/
public class UserDaoTest {@Testpublic void addNewUser() {ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");UserService us =  (UserService)ac.getBean("userService");us.addNewUser(new User());}}
p命名空间注入属性值
示例

打印:

张嘎说:“三天不打小鬼子,手都痒痒!”
Rod说:“世界上有10种人,认识二进制的和不认识二进制的。”

dao层接口

/*** @Author Tuerlechat,* @Date 2022/10/31*/
public interface PersonSayDao {/*** p命名空间注入* @param* @return*/public int userSay();
}

dao层实现

import lombok.Setter;/*** @Author Tuerlechat,* @Date 2022/10/31*/
@Setter
public class PersonSayDaoImpl implements PersonSayDao {private String zg;private String rod;private String say1;private String say2;@Overridepublic int userSay() {System.out.println(zg+"说:"+say1);System.out.println(rod+"说:"+say2);return 0;}
}

配置文件spring.xml

头部引入命名空间

xmlns:p="http://www.springframework.org/schema/p"

引入之后




测试类

/*** @Author Tuerlechat,* @Date 2022/10/31*/
public class PersonSayDaoTest {@Testpublic void userSay() {ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");PersonSayDao psd =  (PersonSayDao)ac.getBean("personSayDao");psd.userSay();}
}
注入各种类型
示例

注入特殊字符、数组、集合。。。等各种类型

用于测试各种类型的实体类

/*** 注入各类型测试实体类*/
public class TestEntity {private String specialCharacter1; // 特殊字符值1private String specialCharacter2; // 特殊字符值2private User innerBean; // JavaBean类型private List list; // List类型private String[] array; // 数组类型private Set set; // Set类型private Map map; // Map类型private Properties props; // Properties类型private String emptyValue; // 注入空字符串值private String nullValue = "init value"; // 注入null值public void setSpecialCharacter1(String specialCharacter1) {this.specialCharacter1 = specialCharacter1;}public void setSpecialCharacter2(String specialCharacter2) {this.specialCharacter2 = specialCharacter2;}public void setInnerBean(User user) {this.innerBean = user;}public void setList(List list) {this.list = list;}public void setArray(String[] array) {this.array = array;}public void setSet(Set set) {this.set = set;}public void setMap(Map map) {this.map = map;}public void setProps(Properties props) {this.props = props;}public void setEmptyValue(String emptyValue) {this.emptyValue = emptyValue;}public void setNullValue(String nullValue) {this.nullValue = nullValue;}public void showValue() {System.out.println("特殊字符1:" + this.specialCharacter1);System.out.println("特殊字符2:" + this.specialCharacter2);System.out.println("内部Bean:" + this.innerBean.getUserName());System.out.println("List属性:" + this.list);System.out.println("数组属性[0和1]:" + this.array[0] + this.array[1]);System.out.println("Set属性:" + this.set);System.out.println("Map属性:" + this.map);System.out.println("Properties属性:" + this.props);System.out.println("注入空字符串:[" + this.emptyValue + "]");System.out.println("注入null值:" + this.nullValue);}
}

配置文件spring.xml


P&GLeoLilyLouisRapkuma呆古米普通犬呆古米海胆kuma我是数据库url我是数据库驱动Tuerlechat,

测试类

/*** @Author Tuerlechat,* @Date 2022/10/31*/
public class TestEntityTest {@Testpublic void testEntity() {ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");TestEntity te = (TestEntity)ac.getBean("testEntity");te.showValue();}
}

结果:

请添加图片描述

利用注解使用IOC

Spring IOC常用注解

@Component:实现Bean组件的定义(创建bean实例)(方便一些项目中的其它业务类使用,比如AOP)

@Repository([实例化名称]) :用于标注DAO类

@Service([实例化名称]) :用于标注业务类

@Controller :用于标注控制器类

@Autowired+@Qualifier("userDao")等价于@Resource(name = "userDao")

注解含义

比如:

package com.xxx.service.impl;@Service
public class UserServiceImpl implements UserService {}

当注解没有被特别设置名字时,相当于我们在spring.xml创建了



当被特别设置名字时

package com.xxx.service.impl;@Service("hank")	//在这里设置个名字为hank
public class UserServiceImpl implements UserService {}

相当于我们在spring.xml创建了



tips:@Component、@Repository、@Service、@Controller 本质并无区别,只是为了开发看着比较方便,实际都是创建bean

注解@Autowired、@Qualifier(“xxx”)和@Resource(name = “xxx”)具体区别
  • Spring下
    • @AutoWired:按数据类型查找
    • @Qualifier(“xxx”):按名字查找
  • tips:一般这两个混合用效果不错的
  • Java下
    • @Resource(name = “xxx”)
      • 不特别设置名字时,先按名字查找,如果名字找不到,再按照数据类型查找(如果还没有那不就报错了嘛。。。)
      • 特别设置名字时,按名字查找
用于深入理解的例子

tips:用IOC、AOP注解前均需记得先设置扫包!!!

一个接口UserDao

/*** @Author Tuerlechat,* @Date 2022/10/31*/
public interface UserDao {/*** 构造注入新增user* @param user* @return*/public int addNewUser(User user);}

两个实现

第一个UserDaoImpl

/*** @Author Tuerlechat,* @Date 2022/10/31*/
@Repository("aa")	//创建这个bean叫aa
public class UserDaoImpl implements UserDao {@Overridepublic int addNewUser(User user) {user.setUserName("张三");System.out.println("新增用户addNewUser == " + user.getUserName());return 0;}
}

第二个UserDaoImpl1

/*** @Author Tuerlechat,* @Date 2022/10/31*/
@Repository("bb")   //创建这个bean叫bb
public class UserDaoImpl1 implements UserDao {@Overridepublic int addNewUser(User user) {user.setUserName("李四");System.out.println("新增用户addNewUserbb == " + user.getUserName());return 0;}
}

业务接口两个方法UserService

/*** @Author Tuerlechat,* @Date 2022/10/31*/
public interface UserService {public int addNewUser(User user);public int addNewUser11(User user);
}

业务实现UserServiceImpl

/*** @Author Tuerlechat,* @Date 2022/10/31*/
@Service
public class UserServiceImpl implements UserService {@Autowired@Qualifier("aa")private UserDao aa;    //将bean(aa)注入到bean(UserServiceImpl)中//如果同一个接口在特殊情况下需要用两次,那么@AutoWired是无法识别的,所以这个时候就需要和@Qualifier配合使用,当然也可以直接用@Resource@Resource(name = "bb")private UserDao bb;    //将bean(bb)注入到bean(UserServiceImpl)中@Overridepublic int addNewUser(User user) {return aa.addNewUser(user);}@Overridepublic int addNewUser11(User user) {return bb.addNewUser(user);}
}

测试类同时调用这两个dao层同一接口的方法(但service层是两个)

/*** 测试类* @Author Tuerlechat,* @Date 2022/10/31*/
public class UserDaoTest {@Testpublic void addNewUser() {ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");UserService us =  (UserService)ac.getBean("userServiceImpl");us.addNewUser(new User());us.addNewUser11(new User());}
}

可以看到两个方法都可以成功运行(说明注入都是成功的)

请添加图片描述

面向切面编程(AOP)

  • AOP的目标:让我们可以“专心做事”
  • AOP原理
    • 将复杂的需求分解出不同方面,将散布在系统中的公共功能集中解决
    • 采用代理机制组装起来运行,在不改变原程序的基础上对代码段进行增强处理,增加新的功能

所谓面向切面编程,是一种通过预编译和运行期动态代理的方式实现在不修改源代码的情况下给程序动态添加功能的技术

  • AOP相关术语
  • 切入点(Pointcut):切哪里(要给哪些方法做增强处理)
  • 增强处理(Advice):想怎么个切法(要哪种增强的方法类型)
    * 前置增强
    * 后置增强
    * 环绕增强、异常抛出增强、最终增强等类型
  • 连接点(Join Point)
  • 切面(Aspect): 切面 = 切入点 + 通知,通俗点就是:在什么时机,什么地方,做什么增强!
  • 目标对象(Target object):给哪个目标类(方法)做增强处理
  • AOP代理(AOP proxy)
  • 织入(Weaving):切好了然后将其拼接好(把增强处理类织入到目标对象中,也可以说是把切面加入到对象,并创建出代理对象的过程。(由 Spring 来完成))

图解

请添加图片描述

五种增强方法

目录说明使用
前置增强在一个方法执行之前,执行通知。before
后置增强在一个方法执行之后,只有在方法成功完成时,执行通知。(如果方法报错了就不会执行了)after-returning
最终增强在一个方法执行之后,不考虑其结果,均执行通知。(类似finally,方法无论是否报错都执行)after
异常增强在一个方法执行之后,只有在方法退出抛出异常时,才能执行通知(报错有异常了就执行了)after-throwing
环绕增强在一个方法执行的前后,同时执行通知。(看起来很像:前置增强+最终增强???😂)around

使用

引用jar包


org.aspectjaspectjweaver1.9.5

创建目标方法:

/*** @Author Tuerlechat,* @Date 2022/10/31*/
@AllArgsConstructor    //有参构造
@NoArgsConstructor     //无参构造
@Setter
public class UserServiceImpl implements UserService {private UserDao userDao;    //构造注入@Overridepublic int addNewUser(User user) {return userDao.addNewUser(user);}}

创建增强处理类

/*** aop切面增强类* @Author Tuerlechat,* @Date 2022/10/31*/
public class UserServiceLogger {/*** 前置增强方法*/public void beforeLogger() {System.out.println("我是前置增强方法,正在打印日志。。。。");}/*** 后置增强方法*/public void afterLogger() {System.out.println("我是后置增强方法,正在打印日志。。。。");}
}

在spring配置文件中引入xml头部,配置aop



xmlns:aop="http://www.springframework.org/schema/aop"

http://www.springframework.org/schema/aop 
http://www.springframework.org/schema/aop/spring-aop.xsd

放好了是这样



execution表达式匹配规则:


然后运行测试类即可

/*** 测试类* @Author Tuerlechat,* @Date 2022/10/31*/
public class UserDaoTest {@Testpublic void addNewUser() {ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");UserService us =  (UserService)ac.getBean("userService");us.addNewUser(new User());}}

利用注解使用AOP

注意:使用之前先扫包

配置文件spring.xml

1、头部文件(扫描包的,粘过了就不用粘了)

命名空间:

xmlns:context="http://www.springframework.org/schema/context"

标签库:

http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.2.xsd

2、代码





然后回到切面注解类

切面注解类UserServiceLogger.java

package com.r.aop;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;import java.util.Arrays;/*** aop切面增强类* @Author Tuerlechat,* @Date 2022/10/31*/
@Aspect //切面注解
@Component  //创建bean实例
public class UserServiceLogger {@Pointcut("execution(* com.r.service..*.*(..))")   //定义切入点(规则),切入点的id就是自己定义的这个方法名pointcutpublic void pointcut() {}/*** 前置增强方法*/@Before("pointcut()")   //设置切入点public void beforeLogger(JoinPoint jp) {System.out.println("我是前置增强方法,正在打印日志。。。。");System.out.println("调用 " + jp.getTarget() + " 的 " + jp.getSignature().getName() + " 方法。方法入参:" + Arrays.toString(jp.getArgs()));}/*** 后置增强方法*/@AfterReturning(pointcut = "pointcut()", returning = "result")  //设置切入点和返回值public void afterReturning(JoinPoint jp,Object result) {System.out.println("我是后置增强方法,正在打印日志。。。。" + result);System.out.println("调用 " + jp.getTarget() + " 的 " +  jp.getSignature().getName() + " 方法。方法返回值:" + result);}/*** 最终增强*/@After("pointcut()")    //设置切入点public void afterLogger() {System.out.println("这是最终增强。");}/*** 异常增强*/@AfterThrowing(pointcut = "pointcut()", throwing = "e") //设置切入点和异常public void afterThrowing(RuntimeException e) {System.out.println("程序发生异常:" + e);}/*** 环绕增强*/@Around("pointcut()")   //设置切入点public Object aroundLogger(ProceedingJoinPoint jp) {System.out.println("环绕增强开始");Object obj = null;  //调用目标方法try {obj = jp.proceed();} catch (Throwable throwable) {throwable.printStackTrace();}System.out.println("环绕增强结束...");return obj;}
}

然后测试类试一下方法就可以了

可以看到结果:

请添加图片描述

看一下异常增强的:

请添加图片描述

tips:测试的时候不要把围绕增强和其它增强同时用,会乱掉(报错的时候后置增强还会出现。。。),具体原因暂时未知(也可能是控制台抽风😑),在这挖个坑

就像这样:

请添加图片描述

AOP事务处理

配置文件

定义事务管理器DataSourceTransactionManager并为其注入数据源Bean





 -->








dao层接口UserDao

/*** 修改用户密码* @param id* @param pwd* @return*/
public int updateUser(@Param("id") Integer id,@Param("pwd") String pwd);}

dao层映射文件UserDao.xml

update smbms_user set userPassword = #{pwd} where id = #{id}

UserService.java

/*** 修改用户密码* @return*/
public int updateUser();

Service实现UserServiceImpl.java

@Override
public int updateUser() {userDao.updateUser(16,"2222");userDao.updateUser(17,null);	//密码不能为空,但改成null让其报错,看数据库是否改变,以此来测试设置的事务是否成功失效return 0;
}

测试类

@Test
public void updateUser() {//读取配置文件ApplicationContext applicationContext =  new ClassPathXmlApplicationContext("spring-mybatis.xml");//获取Service实现beanUserService userService = (UserService) applicationContext.getBean("userServiceImpl");userService.updateUser();
}

运行可以看到控制台显示报错,然后回到数据库会发现两个值都没有改变,就说明事务成功生效了,如果第一个值被正常修改了则说明未生效

使用注解实现AOP事务处理

配置文件只有一行



也就是相当于



















这些代码都不需要配置了

然后再次实现刚才的例子

dao层不用动

Service接口写个新的吧(方便区分嘛)

/*** 修改用户密码(使用注解)* @return*/
public int updateUser1();

UserServiceImpl.java(注解在这里哦,没错就这一个)

@Override
@Transactional(timeout = 1000)    //事务注解,里面可以写配置里面的参数(传播机制...),写到类上代表整个类都开启事务,但一般都是用哪个方法注解哪个即可
public int updateUser1() {userDao.updateUser(16,null);userDao.updateUser(17,"0211");return 0;
}

测试类

@Test
public void updateUser1() {//读取配置文件ApplicationContext applicationContext =  new ClassPathXmlApplicationContext("spring-mybatis.xml");//获取Service实现beanUserService userService = (UserService) applicationContext.getBean("userServiceImpl");userService.updateUser1();
}

运行结果是一样的,看一看就知道了

Spring应用扩展

使用注解指定Bean的作用域

使用@Scope注解指定Bean的作用域(和maven的差不多)

@Scope("prototype") 
@Service("userService") 
public class UserServiceImpl implements UserService {// 省略其他代码
}
bean的作用域
作用域说 明
单例(Singleton)默认值。Spring以单例模式创建Bean的实例,即在整个应用中,容器中该Bean的实例只有一个
原型(Prototype)每次从容器中获取Bean时,都会创建一个新的实例
请求(Request)用于Web应用环境,针对每次HTTP请求都会创建一个实例
会话(Session)用于Web应用环境,同一个会话共享同一个实例,不同的会话使用不同的实例
全局会话(global session)仅在Portlet的Web应用中使用,同一个全局会话共享一个实例。对于非Portlet环境,等同于session

Spring自动装配

自动装配:Spring可以根据属性类型、名称等自动进行注入

使用

设置元素的autowire属性



Spring提供的4种自动装配类型
取值说明
no默认值。Spring 默认不进行自动装配,必须显式指定依赖对象
byName根据属性名自动装配。Spring 自动查找与属性名相同的id,如果找到,则自动注入,否则什么都不做
byType根据属性的类型自动装配。Spring 自动查找与属性类型相同的Bean,如果刚好找到唯一的那个,则自动注入;如果找到多个与属性类型相同的Bean,则抛出异常;如果没找到,就什么也不做
constructor和byType 类似,不过它针对构造方法。如果 Spring 找到一个Bean和构造方法的参数类型相匹配,则通过构造注入该依赖对象;如果找不到,将抛出异常
设置全局自动装配(可以但不推荐)

可以为元素设置default-autowire属性,影响全局

	

tips:自动装配使得配置文件可以非常简洁,但同时也造成组件之间的依赖关系不明确,容易引发一些潜在的错误,在实际项目中要谨慎使用

拆分策略—拆分配置文件

1、公用配置+每个系统模块一个单独配置文件(包含DAO、Service、Web控制器)
2、公用配置+DAO Bean配置+业务逻辑Bean配置+Web控制器配置

两种策略各有特色,适用于不同场合

引入拆分后的配置文件

利用ClassPathXmlApplicationContext 的重载方法可以配置多个配置文件,用逗号隔开或者使用通配符(*)

1、用逗号隔开

ApplicationContext ac = new ClassPathXmlApplicationContext("application.xml", "application-dao.xml", "application-service.xml");

2、用String[]数组传入

//定义一个String[]数组
String[] str = {"application.xml", "application-dao.xml", "application-service.xml"};
//传入这个数组
ApplicationContext ac = new ClassPathXmlApplicationContext(str);

3、使用通配符(*)

ApplicationContext ac = new ClassPathXmlApplicationContext("application*.xml");

tips:使用这种方式配置的时候注意命名要有较统一的格式

4、可以在Spring的配置文件中通过标签下的import来进行导入其他配置文件,来把他们都整合到一起,以此来形成一个完整的Spring配置文件



Spring 能帮我们做什么

①.Spring 能帮我们根据配置文件创建及组装对象之间的依赖关系。
②.Spring 面向切面编程能帮助我们无耦合的实现日志记录,性能统计,安全控制。
③.Spring 能非常简单的帮我们管理数据库事务。
④.Spring 还提供了与第三方数据访问框架(如Hibernate、JPA)无缝集成,而且自己也提供了一套JDBC访问模板来方便数据库访问。
⑤.Spring 还提供与第三方Web(如Struts1/2、JSF)框架无缝集成,而且自己也提供了一套Spring MVC框架,来方便web层搭建。
⑥.Spring 能方便的与Java EE(如Java Mail、任务调度)整合,与更多技术整合(比如缓存框架)。

相关内容

热门资讯

银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...
​ToDesk 远程工具安装及... 目录 前言 ToDesk 优势 ToDesk 下载安装 ToDesk 功能展示 文件传输 设备链接 ...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWS管理控制台菜单和权限 要在AWS管理控制台中创建菜单和权限,您可以使用AWS Identity and Access Ma...