- Spring是轻量级的开源的JavaEE框架。
- Spring可以解决企业应用开发的复杂性
- Spring有两个核心的部分:IOC 和 AOP
- IOC:控制反转,把创建对象过程交给Spring进行管理
- AOP:面向切面,不修改源代码进行功能管理
Spring特点:
- 方便解耦,简化开发
- AOP编程支持
- 方便程序测试
- 方便和其他框架进行整合
- 方便进行事务操作
- 降低API开发难度
jar包下载地址:https://repo.spring.io/release/org/springframework/spring/
案例11 创建spring的核心配置文件
2 创建实体类
public class Student {
private Integer sid;
private String sname;
private String sex;
private Integer sage;
private Boolean sdy;
...
}
3 在核心配置文件中通过bean标签来创建对象
4 测试类
//创建spring上下文对象 关联核心配置文件
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("com/zhiyou/ioc/spring1.xml");
//通过上下文对象的getbean方法 由bean的name值获取javabean对象
Student stu1=(Student)context.getBean("s1");
System.out.println(stu1);
Student stu2=(Student)context.getBean("s2");
System.out.println(stu2);
context.close();
二、IOC容器
- IOC思想基于IOC容器完成,IOC容器底层就是对象工厂
- Spring提供IOC容器实现的两种方式:(两个接口)
- BeanFactory,IOC容器基本实现,是Spring内部使用接口,不提供给开发人员进行使用
*加载配置文件时不会创建对象,在获取对象时才创建对象
2.APPlicationContext ,BeanFactory的子接口,提供更多强大的功能,一般由开发人员使用
*加载配置文件时就会把在配置文件对象进行创建
3、APPlicationContext接口的实现类
1)FileSystemXmAPPlicationContext 2)ClassPathXmAPPlicationContext
写路径时如果是FileSystemXmAPPlicationContext 则写盘符所在路径
写路径时如果是ClassPathXmAPPlicationContext 则写src 下的路径
1、xml配置方式创建对象2、xml方式注入属性 1) set方式注入属性
前提:实体类必须有set方法
property标签 name为属性的名字 value为属性的值
2)构造方法的方式注入属性
ioc创建对象时,会默认使用实体类中的无参构造方法
用构造方法赋值时,需要声明有参的构造方法
3、注入其他类型的属性 1)null值
2)对象类型
用ref引入另一个bean
3)数组和集合类型属性
4、bean的作用域111 112 113 114
21 31 41 22 32 42 22 32 42
在 spring 配置文件 bean 标签里面有属性(scope)用于设置单实例还是多实例 scope 属性值
| 作用域 | 描述 |
| 单例(singleton) | (默认)每一个Spring IoC容器都拥有唯一的一个实例对象 |
| 原型(prototype) | 一个Bean定义,任意多个对象 |
| 请求(request) | 一个HTTP请求会产生一个Bean对象,也就是说,每一个HTTP请求都有自己的Bean实例。只在基于web的Spring ApplicationContext中可用 |
| 会话(session) | 限定一个Bean的作用域为HTTPsession的生命周期。同样,只有基于web的Spring ApplicationContext才能使用 |
| 全局会话(global session) | 限定一个Bean的作用域为全局HTTPSession的生命周期。通常用于门户网站场景,同样,只有基于web的Spring ApplicationContext可用 |
bean的懒加载:默认情况下scope=singleton的bean 项目启动spring容器加载核心配置文件就会创建bean对应的对象
开头通过lazy-init="true"属性来指定 bean标签第一次被调用时才创建对象
6、bean的生命周期
生命周期:从对象创建到对象销毁的过程
(1)通过构造器创建 bean 实例(无参数构造)
(2)为 bean 的属性设置值和对其他 bean 引用(调用 set 方法)
(3)调用 bean 的初始化的方法(需要进行配置初始化的方法)
(4)bean 可以使用了(对象获取到了)
(5)当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法)
其中初始化和销毁方法需要自定义,并且在配置文件中配置,用bean标签中属性指定
7、属性的自动装配(自动关联的属性赋值)autowire="byName":自动给对象类型的属性赋值:bean名字和属性名一致
autowire="byType":如果找到一个指定类型的bean 直接赋值
如果找到多个 赋值bean的名字与属性名相同的
如果找到多个 但没有bean的名字与属性名字相同的 报错:UnsatisfiedDependencyException
8、注解形式的ioc
Spring 创建对象提供注解
(1)@Component
(2)@Service
(3)@Controller
(4)@Repository
Spring 属性注入提供注解
(1)@Autowired:根据属性类型进行自动装配
(2)@Qualifier:根据名称进行注入,要和@Autowired一起使用
(3)@Resource:可以根据类型注入,也可以根据名称注入
(4)@Value:注入普通类型属性
1)在核心配置文件中引入context的命名空间和xsd2)使用context标签指定添加了注解的实体类的位置
3)在实体类上添加注解
//@Repository //创建bean的注解:给dao持久层的类添加的注解
//@Controller //创建bean的注解:给controller控制层的类添加的注解
//@Service //创建bean的注解:给service业务层的类添加的注解
@Component("s2") //创建bean的注解:不确定当前bean具体属于那一层 可以加属性:用于指定bean的名字 不加默认是类名首字母小写
//@Scope("prototype") //指定bean的作用域
@Lazy//懒加载 只适用于单例模式
public class Student {
{
System.out.println("构造代码块!!");
}
//@Value("1001")给属性赋值:可以加载属性上 也可以加在set方法上
@Value("1001")
private Integer sid;
@Value("韩庚")
private String sname;
@Value("男")
private String sex;
@Value("19")
private Integer sage;
private Boolean sdy;
//@Autowired //自动装配:策略和byType类似
//@Resource(name="teacher")//自动装配:name指定bean的名字
@Resource
private Teacher teacher;
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
public Integer getSid() {
return sid;
}
public void setSid(Integer sid) {
this.sid = sid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Integer getSage() {
return sage;
}
public void setSage(Integer sage) {
this.sage = sage;
}
public Boolean getSdy() {
return sdy;
}
@Value("true")
public void setSdy(Boolean sdy) {
this.sdy = sdy;
}
@Override
public String toString() {
return "Student [sid=" + sid + ", sname=" + sname + ", sex=" + sex + ", sage=" + sage + ", sdy=" + sdy
+ ", teacher=" + teacher + "]";
}
public Student(Integer sid, String sname, String sex, Integer sage, Boolean sdy) {
super();
this.sid = sid;
this.sname = sname;
this.sex = sex;
this.sage = sage;
this.sdy = sdy;
}
public Student() {
super();
}
@PostConstruct
public void initMethod(){
System.out.println("public void initMethod()");
}
@PreDestroy
public void destroyMethod(){
System.out.println("public void destroyMethod()");
}
}
4)@Resource和@Autowired的区别
三、AOP容器其实@Resource并不是Spring的注解,它的包是javax.annotation.Resource
@Resource默认按照ByName方式注入,有name和type两个属性,分别是按照名称和按照类型注入,如果这两个属性都没有指定就会按默认方式注入,也可以两个同时指定
@Autowired默认按照ByType方式注入,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置它的required属性为false。如果想要按照ByName方式需要配合@Qualifier注解一起使用,指定@Qualifier的value属性值为要注入的bean的名字
(1)面向切面编程(方面),利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得 业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
(2)通俗描述:不通过修改源代码方式,在主干功能里面添加新功能
1、aop术语(1)连接点:类里面哪些方法可以被增强,这些方法成为连接点
(2)切入点:实际被真正增强的方法,成为切入点
(3)通知(增强):实际增强的逻辑部分称为通知(增强)
通知的类型:*前置通知 *后置通知 *环绕通知 *异常通知 *最终通知
(4)切面(是动作):把通知应用到切入点的过程
2、切入点表达式(1)切入点表达式作用:知道对哪个类里面的哪个方法进行增强
(2)语法结构: execution([权限修饰符] [返回类型] [类全路径] [方法名称]([参数列表]) )
* 代表全部
举例 1:对 com.zhiyou.dao.BookDao 类里面的 add 进行增强
execution(* com.zhiyou.dao.BookDao.add(..))
举例 2:对 com.zhiyou.dao.BookDao 类里面的所有的方法进行增强
execution(* com.zhiyou.dao.BookDao.* (..))
举例 3:对 com.zhiyou.dao 包里面所有类,类里面所有方法进行增强
execution(* com.zhiyou.dao.*.* (..))
3、通知类型@Before注解表示作为前置通知
@After注解表示作为最终通知
@AfterReturning注解表示作为后置通知
@AfterThrowing注解表示作为异常通知
@Around注解表示作为环绕通知
注意:After与AfterReturning的区别:
After无论如何都执行,也称为最终通知
AfterReturning发生异常时不执行,称为后置通知或返回通知
4、基于xml配置方式的aop 1)导入jar包 2)创建目标实体类定义方法,并抽取接口public class Student implements Serializable, StudentInterface{
private String sname;
public int addHao(int a,int b){
System.out.println("学生'"+sname+"'正在算术:"+a+"+"+b+"="+(a+b));
return a+b;
}
public void eatHao(String food){
System.out.println("学生'"+sname+"'正在吃饭:'"+food+"'真香!");
}
public void smokeCha(String name){
System.out.println("学生'"+sname+"'正在吸烟:'"+name+"'吞云吐雾!");
}
public void sleepHao(){
System.out.println("学生'"+sname+"'正在休息:劳逸结合!");
}
public void gameCha(String gname){
System.out.println("学生'"+sname+"'正在玩游戏:玩物丧志!");
}
....
}
3)创建代理实体类,配置通知方法
//创建实体类 封装所有的辅助功能
public class MyAdvice {
public void after1AdviceMethod(){
System.out.println("..........after1AdviceMethod111111111");
}
public void after2AdviceMethod(){
System.out.println("..........after2AdviceMethod222222222");
}
public void beforeAdviceMethod(){
System.out.println("beforeAdviceMethod..................");
}
public void exceptionAdviceMethod(Exception e){
System.out.println("exceptionAdviceMethod................."+e);
}
public Object aroundAdviceMethod(ProceedingJoinPoint pjp){
System.out.println("around-----------1");
Object result=null;
try {
result=pjp.proceed();
} catch (Throwable e) {
throw new RuntimeException(e);
}
System.out.println("around-----------2");
return result;
}
}
4) 在核心配置文件中声明:context和aop的命名空间和xsd
5)创建目标bean和代理bean
6) 通过aop标签实现织入
7)测试
// //创建spring上下文对象 关联核心配置文件
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("com/zhiyou/spring.xml");
StudentInterface studentProxy=(StudentInterface)context.getBean("stu2");
studentProxy.eatHao("黄焖鸡");
System.out.println();
studentProxy.gameCha("CS");
System.out.println();
studentProxy=(StudentInterface)context.getBean("stu");
studentProxy.eatHao("黄焖鸡");
System.out.println();
studentProxy.gameCha("CS");
context.close();
4、基于注解方式aop
增强类也就是代理类要用@AspectJ注解
1)创建核心配置文件引入context和aop的命名空间和xsd文件2)在核心配置文件通过context标签指定扫描的实体类包
3)创建封装目标实体类并抽取接口
@Component
public class Teacher implements Serializable, TeacherInterface{
@Value("1")
private Integer tid;
@Value("张老师")
private String tname;
@Value("3000")
private Float tsalary;
public void eatHao(String food){
System.out.println("老师'"+tname+"'正在吃饭:'"+food+"'真香!");
}
public int teachHao(int a){
System.out.println("老师'"+tname+"'正在授课::求"+a+"的三次方");
//System.out.println(1/0);
return (int)Math.pow(a, 3);
}
public void smokeCha(String name){
System.out.println("老师'"+tname+"'正在吸烟:'"+name+"'吞云吐雾,注意身体!");
}
...
}
//创建主流业务的实体类
@Component
public class Student implements Serializable, StudentInterface{
@Value("韩梅梅")
private String sname;
@Value("1001")
private Integer sid;
@Value("99")
private Float score;
@Autowired
private TeacherInterface teacher;
public int addHao(int a,int b){
System.out.println("学生'"+sname+"'正在算术:"+a+"+"+b+"="+(a+b));
return a+b;
}
public void eatHao(String food){
System.out.println("学生'"+sname+"'正在吃饭:'"+food+"'真香!");
}
public void smokeCha(String name){
System.out.println("学生'"+sname+"'正在吸烟:'"+name+"'吞云吐雾!");
}
public void sleepHao(){
System.out.println("学生'"+sname+"'正在休息:劳逸结合!");
}
public void gameCha(String gname){
System.out.println("学生'"+sname+"'正在玩游戏:玩物丧志!");
return;
}
...
}
4)创建增强实体类,并配置通知
@Component
@Aspect //指定当前bean是通知bean
public class MyAdvice {
//通过注解@Pointcut定义切入点
@Pointcut("execution(* com.zhiyou100.day05.*.*Hao(..))")
public void haoPointCut() {}//方法名 即为切入点的id
//通过注解@Pointcut定义切入点
@Pointcut("execution(* com.zhiyou100.day05.*.*Cha(..))")
public void chaPointCut() {}//方法名 即为切入点的id
//通过注解@Pointcut定义切入点
@Pointcut("execution(* com.zhiyou100.day05.*.*(..))")
public void allPointCut() {}//方法名 即为切入点的id
//@After(value="execution(* com.zhiyou100.day05.*.*Hao(..))")
@After(value="haoPointCut()")
public void after1AdviceMethod(JoinPoint jp){
System.out.println("..........after1AdviceMethod111111111::"+jp.getSignature().getName());
}
//@AfterReturning(value="execution(* com.zhiyou100.day05.*.*Hao(..))",returning="result")
@AfterReturning(value="haoPointCut()",returning="result")
public void after2ReturningAdviceMethod(Object result){
System.out.println("..........after2AdviceMethod222222222:::返回值是"+result);
}
//@Before(value="execution(* com.zhiyou100.day05.*.*Hao(..))")
@Before(value="haoPointCut()")
public void beforeAdviceMethod(JoinPoint jp){
System.out.println("beforeAdviceMethod.................:::"+jp.getSignature().getName());
}
@AfterThrowing(value="allPointCut()",throwing="e")
//@AfterThrowing(value="execution(* com.zhiyou100.day05.*.*(..))",throwing="e")
public void exceptionAdviceMethod(Exception e){
System.out.println("exceptionAdviceMethod................."+e);
}
//@Around(value="execution(* com.zhiyou100.day05.*.*Cha(..))")
@Around(value="chaPointCut()")
public Object aroundAdviceMethod(ProceedingJoinPoint pjp){
System.out.println("around-----------1");
Object result=null;
try {
result=pjp.proceed();
} catch (Throwable e) {
throw new RuntimeException(e);
}
System.out.println("around-----------2");
return result;
}
}



