spring框架笔记

本文详细介绍了Spring框架中的IOC(控制反转)和DI(依赖注入)概念,包括配置文件中的bean定义、对象创建时机、基于XML和注解的DI实现方式。此外,讲解了set注入和构造注入的使用,以及引用类型的自动注入原理。同时,文章探讨了面向切面编程(AOP)的概念,如动态代理、切面、通知类型及其应用场景,并展示了AOP注解的使用。最后,提到了Spring事务管理的注解驱动方式。
摘要由CSDN通过智能技术生成

1.ioc概念

是在容器中来实现对象的创建的,能创建对象,能给对象赋值

2.spring的配置文件

(1)beans:是根标签,spring把java对象成为bean
(2)spring创建对象:
声明bean,就是告诉spring创建对象,一个bean就是一个对象
id:对象的自定义名称,唯一值
class:类的全限定名称

3.spring默认创建对象的时间:在创建spring的容器时,会创建配置文件中的所有的对象。

4.di的实现有两种

(1)在spring的配置文件中,使用标签和属性完成,叫做基于XML的di实现
(2)使用spring中的注解,完成属性赋值,叫做基于注解的di实现

4.1 di的语法分类

(1)set注入(设置注入):spring调用类的set方法,在set方法可以实现属性的赋值
80%左右都是使用的set注入
(2)构造注入,spring调用类的有参数构造方法,创建对象。在构造方法中完成赋值。

School:

package com.bjpowernode.ba05;
public class School {
    private String name;
    private String address;
    public void setName(String name) {
        this.name = name;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    @Override
    public String toString() {
        return "School{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

Student:

package com.bjpowernode.ba05;
import com.bjpowernode.ba05.School;
public class Student {
    private String name;
    private int age;//声明一个引用类型数据
    private School school;
    public void setName(String name) {
        this.name = name;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public void setSchool(School school) {
        this.school = school;
        System.out.println("set"+school);
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", school=" + school +
                '}';
    }
}

4.2set注入(设置注入):spring调用类的set方法,你可以在set方法可以实现属性的赋值

1)简单类型的set注入
<bean id="XXX" class="YYY">
              <property name="name" value="张三"></property>
              <property name="age" value="20"></property>
       </bean>

结果:student对象 = Student{name=‘张三’, age=20}

设置注入的注意事项:
(1)先调用类的无参构造创建对象,再调用执行set方法完成赋值
(2)引用类型的set注入:spring调用类的set方法

<bean id="xxx" class="yyy">
     <property name="属性名称" ref="bean的id(对象的名称)"/>
</bean>

例如:

<bean id="myStudent" class="com.ba01.Student">
          <property name="name" value="李四"></property>
          <property name="age" value="26"></property>
          <!--引用类型-->
          <property name="school" ref="mySchool"></property>
   </bean>
   <bean id="mySchool" class="com.ba01.School">
   		  <property name="name" value="北京大学"></property>
          <property name="address" value="五道口"></property>
   </bean>

4.3构造注入:spring调用类有参数构造方法,在创建对象的同事,在构造方法中给属性赋值

构造注入使用<constructor-arg>标签
<constructor-arg>属性有:
	name:表示构造方法的形参名
	index:表示构造方法的参数的位置,参数从左往右位置从0开始
	value:构造方法的形参类型是简单类型,使用value
	ref:构造方法的形参类型是引用类型的,使用ref

4.4引用类型的自动注入:spring使用规则给引用类型赋值,常用的是byName,byType

1)byName(按名称注入):java类中引用类型的属性名和spring容器(配置文件)<bean>的id名称
					 且数据类型是一致的,这样的容器中的bean,spring就能赋值给引用类型

语法:

<bean id="xx" class="yyy" autowire="byName">
			简单类型属性赋值
		</bean>
		<bean id="myStudent" class="com.bjpowernode.ba05.Student" autowire="byName">
              <property name="name" value="李四"/>
              <property name="age" value="30"/>
       </bean>
       <bean id="school" class="com.bjpowernode.ba05.School">
              <property name="name" value="人民大学"/>
              <property name="address" value="人民大学区"/>

byName的结果:
setSchool{name=‘人民大学’, address=‘人民大学区’}
Student{name=‘李四’, age=30, school=School{name=‘人民大学’, address=‘人民大学区’}}

2)byType(按类型注入):java类中引用类型的数据类型和spring容器中(配置文件)<bean>的class
					  是同源关系的,这样的bean能够赋值给引用类型
	语法:
		<bean id="xx" class="yyy" autowire="byType">
			简单类型属性赋值
		</bean>
<bean id="myStudent" class="com.ba05.Student" autowire="byType">
              <property name="name" value="李四"/>
              <property name="age" value="30"/>
       </bean>
       <bean id="mySchool" class="com.ba05.School">
              <property name="name" value="广西大学"/>
              <property name="address" value="广西大学区"/>
       </bean>
   byName的结果:
   		setSchool{name='广西大学', address='广西大学区'}
		Student{name='李四', age=30, school=School{name='广西大学', address='广西大学区'}}

	注:同源就是一类的意思:
		1.java类中引用类型的数据类型和bean的class的值是一样的
		2.java类中引用类型的数据类型和bean的class的值父子类关系的
		3.java类中引用类型的数据类型和bean的class的值接口和实现类关系的

4.5:注解

1)component:创建对象的,等同于<bean>的功能
   属性:value  就是对象的名称,也就是bean的id值
   @Component(value = "myStudent")
   component的三种使用方式:
   1.使用value属性,指定对象名称
     @Component(value = "myStudent")
   2.省略value
   	 @Component("myStudent")
   3.不指定对象名称,由spring提供默认名称:类名的首字母小写
2) spring中和@Component功能一致,创建对象的注解还有:
   1.@Repository(用在持久层类的上面):放在dao的实现类上面
   				表示创建dao对象,dao对象是能访问数据库的
   2.@Service(用在业务层类的上面):放在service的实现类上面
   				创建service对象,service对象是做业务处理,可以有事务等功能的
   3.@Controller(用在控制器的上面):放在控制器(处理器)类的上面
   				创建控制器对象的,控制器对象,能够接受用户提交的参数,显示请求的处理结果
   	以上三个注解的使用语法和@Component一样的,都能创建对象,但是这三个注解还有额外的功能
   	@Repository,@Service,@Controller是给项目的对象分层的。


3)引用类型
   @Autowired:spring框架提供的注解,实现引用类型的赋值
   spring中通过注解给引用类型赋值,使用的是自动注入原理,支持byName,byType,默认byType
   @Atuowired:默认使用的是byType自动注入
   位置:1.在属性定义的上面,无需set方法,推荐使用
   	     2.在set方法的上面
   如果要使用byName方式,需要做的是:
   1.在属性上面加入@Autowired
   2.在属性上面加入@Qualifier(value="bean的id"):表示使用指定名称的bean完成赋值

   @Resource:来自jdk中的注解,spring框架提供,可以使用它给引用类型赋值
   			  使用的也是自动注入原理,支持byName,byType,默认是byName
   	先使用byName自动注入,如果byName赋值失败,再使用byType

5.aop–面向切面编程,基于动态代理。

1)动态代理
	实现方式:jdk动态代理,使用jdk中的proxy,method,InvocationHanderl创建代理对象
			 jdk动态代理要求目标类必须实现接口

	cglib动态代理:第三方工具库,创建代理对象,原理是继承,通过继承目标类,创建子类
				  子类就是代理对象,要求目标类不能是final的,方法也不能是final的

2)动态代理的作用:
	1.在目标类源代码不改变的情况下,增加功能
	2.减少代码的重复
	3.专注业务逻辑代码
	4.解耦合,让你的业务功能和日志,事务非业务功能分离
Aspect:切面,给你的目标类增加的功能,就是切面
切面的特点:一般都是非业务方法,独立使用的

怎么理解面向切面编程?
1.需要在分析项目功能时,找出切面
2.合理的安排切面的执行时间(在目标方法钱,还是在目标方法后)
3.合理的安排切面执行的位置,在哪个类,哪个方法增强功能

5.1aop中的注解

1.@Aspect:是aspectj框架中的注解

	  作用:表示当前类是切面类
	  切面类:是用来给业务方法增加功能的类,在这个类中有切面的功能代码
	  位置:在类定义的上面
	@@Aspect
	public class MyAspect{
		/*
		  定义方法,方法是实现切面功能的
		  方法的定义要求:
		  1.公共方法public
		  2.方法没有返回值
		  3.方法名称自定义
		  4.方法可以有参数,也可以没有参数
		  	如果有参数,参数不是自定义的,有几个参数类型可以使用
		
		  @Before:前置通知注解
		  	 属性:value,是切入点表达式,表示切面的功能执行的位置
		  	 位置:在方法的上面
		  特点:
		     1.在目标方法之前先执行的
		     2.不会改变目标方法的执行结果
		     3.不会影像目标方法的执行
		*/
	@Before(value = "execution(void com.bjpowernode.ba01.SomeServiceImpl.doSome(String, Integer))")
	public void myBefore(JoinPoint jp){ //JoinPoint
    System.out.println("方法的签名="+jp.getSignature());
    System.out.println("方法的名称="+jp.getSignature().getName());
    System.out.println("前置通知,切面功能:在目标方法之前执行"+new Date());
    Object obj [] = jp.getArgs();
    for (Object arg:obj){
        System.out.println("参数="+arg);
    }
}

在这里插入图片描述

2.JoinPoint:业务方法,要加入切面功能的业务方法

	 作用是:可以在通知方法中获取方法执行时的信息,例如方法名称,方法的实参
	 如果你的切面功能中需要用到的方法信息,就加入JoinPoint
	 这个JoinPoint参数的值是由框架赋予,必须是第一个位置的参数
	 结果:可以看上面的代码和截图

3.后置通知定义方法,方法是实现切面功能的

方法的定义要求:
1.公共方法public
2.方法没有返回值
3.方法名称自定义
4.方法可以有参数,推荐是object,参数名自定义

@AfterReturning:后置通知
属性:1.value 切入点表达式
2.returning 自定义的变量,表示目标方法的返回值。
自定义变量名必须和通知方法的形参名一样
位置:在方法定义的上面
特点:
1.在目标方法之后执行的
2.能够获取到目标方法的返回值,可以根据这个返回值做不同的处理功能
3.可以修改这个返回值

@Aspect
public class myAspect {
	@AfterReturning(value = "execution(* *..SomeServiceImpl.doOther(..))",returning = "res")
	public void myAfterReturning(Object res){
		System.out.println("后置通知:=" + res);
	}
}

在这里插入图片描述

4.环绕通知方法的定义格式

		1.public
		2.必须有一个返回值,推荐使用Object
		3.方法名称自定义
		4.方法有参数,固定的参数ProceedingJoinPoint
	@Around:环绕通知
		属性:value 切入点表达式
		位置:在方法的定义上面
	特点:
		1.他是功能最强的通知
		2.在目标方法的前和后都能增强功能
		3.控制目标方法是否被调用执行
		4.修改原来的目标方法的执行结果,影响最后的调用结果
@Around(value = "execution(* *..SomeServiceImpl.doFirst(..))")
    	public Object myAround(ProceedingJoinPoint jp) throws Throwable {
        	Object result = null;
        	System.out.println("环绕通知,在方法之前执行=");
       		result = jp.proceed();
        	System.out.println("环绕通知,在方法之后执行=" );
        	return result;
    	}

在这里插入图片描述

5.异常通知

	@AfterThrowing:异常通知
		属性:value 切入点表达式
			 throwing 自定义变量,表示目标方法抛出的异常对象
			 变量名必须和方法的参数名一样
	特点:1.在目标方法抛出异常时执行的
		 2.可以做异常的监控程序,监控目标方法执行时是不是有异常。
		 如果有异常,可以发送邮件,短信进行通知

6.最终通知

	@After:最终通知
		属性:value 切入点表达式
		位置:方法的上面
	特点:1.总是会执行
		 2.在目标方法之后执行的
		 一般做资源清除工作的

7.使用cglib动态代理

	如果目标类没有接口,使用cglib动态代理,spring会自动应用cglib
	如果目标类有接口,期望使用cglib,proxy-target-class="true":告诉框架,要使用cglib动态代理
	<aop:aspectj-autoproxy proxy-target-class="true"/>

5.2使用spring管理事务

中小型项目使用注解:

1)声明事务管理器
   <bean id="transactionManager" class="org.springframework.jdbc.datesource.DateSourceTransactionManager"
   	<property name="dateSource" ref="myDateSource"/>
   </bean>
2)开启事务注解驱动,告诉spring使用注解管理事务,创建代理对象
	transaction-manager:事务管理器对象的id
<tx:annotation-driven transaction-manager="transactionManager"/>
3)在方法上加@Transactional即可

大型项目使用aspectj:

1)配置aop:
	<!--配置切入点表达式:指定那些包中类,要使用事务
		id:切入点表达式的名称,唯一值
		expression:切入点表达式,指定哪些类要使用事务,aspectj会创建代理对象
	-->
	<aop:config>
		<aop:config id="servicePt" expression="execution(* *..service..*.*(..))"/>
		<!--配置增强器:关联advice和pointcut
			advice-ref:通知,上面tx:advice哪里的配置
			pointcut-ref:切入点表达式的id
		-->
		<aop:advisor advice-ref="myAdvice" pointcut-ref="servicePt"/>
	</aop:config>

2)声明事务管理器
   <bean id="transactionManager" class="org.springframework.jdbc.datesource.DateSourceTransactionManager"
   	<property name="dateSource" ref="myDateSource"/>
   </bean>

3)配置事务属性
	<!--tx:methon给具体的方法配置事务属性
		name:方法名称
		porpagation:传播行为
		isolation:隔离级别
		rollback-for:你指定的异常类名,发生异常一定回滚
	-->
<tx:advice id="myAdvice" transaction-manager="transactionManager">
	<tx:attributes>
		<tx:method name="buy" porpagation="REQUIRED" isolation="DEFAULT"
			rollback-for="异常"
	</tx:attributes>
<tx:advice/>

这个是本人看动力节点的学习笔记,如有错误之处,还望指出,谢谢大家。
2021-4-19,spring学习完成

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值