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学习完成