一.springIOC(控制反转)
Spring IOC作用:
springIOC:springIOC容器扮演项目的载体,管理整个Java项目,ioc容器可以使得项目更符合
高内聚,低耦合的变成思想,"解耦"
耦合:类与类有耦合,方法与方法有耦合
解耦: 1.尽量避免new对象,通过反射实例化
2.需要创建的对象不要写死,而是把类名保存在独立的properties文件中,按需加载
springIOC:控制反转
● 关键字:IOC名词解释,作用是解耦,使用IOC容器管理项目组件之间的耦合关系
● IOC( Inversion of Control,中文释义:控制反转 ) 是Spring框架的核心思想之一,
主要用于解耦。IOC是指将创建对象的控制权转移给Spring框架进行管理。
由Spring框架根据配置文件或注解等方式,创建bean对象并管理各个bean对象之间的依赖关系。
使对象之间形成松散耦合的关系,实现解耦;
○ 控制 :指的是对象创建(实例化、管理)的权力
○ 反转 :控制权交给外部环境(Spring框架、IoC容器)
springIOC使用步骤:
1.创建类
2.将需要spring管理的类,注入springIOC容器(在Spring的配置文件中完成)
<bean id="唯一标识" class="类的完全限定名称"></bean>
3.以解耦方式获取javaBean实例对象
3.1加载spring主配置文件,获取spring核心对象
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
3.2获取javaBean
Student student = (Student) applicationContext.getBean("student");
//将bean对象放入IOC容器
<bean id="dao" class="com.apesource.dao.UserdaoImpl"></bean>
//获取容器
ClassPathXmlApplicationContext context = new lassPathXmlApplicationContext("beans.xml");
//获取bean
UserServiceImpl userService=(UserServiceImpl) context.getBean("service");
IOC容器有关的关键字:
接口
BeanFactory(父接口):多例模式
ApplicationContext(子接口):默认单例模式
实现类
ClassPathXmlApplicationContext:通过相对路径加载主配置文件
FileSystemXmlApplicationContext:通过绝对路径加载主配置文件
AnnotationConfigApplicationContext:加载配置"类"
二.springDI(依赖注入)
Spring DI 的理解:
DI(Dependecy Inject,中文释义:依赖注入)
是对IOC概念的不同角度的描述,是指应用程序在运行时,每一个bean对象都依赖IOC容器
注入当前bean对象所需要的另外一个bean对象。
(例如在MyBatis整合Spring时,SqlSessionFactoryBean 依赖IOC容器注入一个DataSource数据源bean);
springDI实现方式:
1.set注入
2.构造注入
3.注解注入
springDI支持的数据类型:
1.基本类型与String
2.javaBean对象
3.复杂类型(构造注入不支持)
di实现步骤(set)
1.思考该注入什么Bean对象,该往哪个bean对象中注入
2.提供对应方法(set) setXXXX()<必须提供>
3.配置
<property 属性名="属性值"></property>
属性:
name:属性名
ref:注入的值的引用
value:注入的值
<bean id="student" class="com.apesource.pojo.Student">
<property name="stuname" value="闫亚东"></property>
<property name="stuhobby" value="羽毛球"></property>
<property name="stuAge" value="23"></property>
//注入容器中已有student的bean对象
<property name="myStu" ref="student" ></property>
</bean>
di实现步骤(构造)
1.思考思考该注入什么Bean对象,该往哪个bean对象中注入
2.提供对应方法(构造)
3.配置
<constructor-arg 属性名="属性值"></constructor-arg>
属性:
name:属性名
type: 参数类型
index: 参数下标
ref:注入的值的引用
value:注入的值
<bean class="com.apesource.pojo.Student" id="student2">
<constructor-arg name="stuname" value="余承东"></constructor-arg>
<constructor-arg name="stuhobby" value="IT技术"></constructor-arg>
<constructor-arg name="stuAge" value="45"></constructor-arg>
</bean>
<bean class="com.apesource.pojo.Student" id="student3">
<constructor-arg type="java.lang.String" value="任正非"></constructor-arg>
<constructor-arg type="java.lang.String" value="报国"></constructor-arg>
<constructor-arg type="int" value="65"></constructor-arg>
</bean>
<bean class="com.apesource.pojo.Student" id="student4">
<constructor-arg index="0" value="张勇"></constructor-arg>
<constructor-arg index="1" value="搞汽车"></constructor-arg>
<constructor-arg index="2" value="43"></constructor-arg>
</bean>
复杂数据类型的set注入:
<!--复杂数据类型的set注入-->
<bean id="teacher" class="com.apesource.pojo.Teacher">
<!--javabean注入-->
<property name="myStu" ref="student" ></property>
<constructor-arg name="myStu" ref="student4"></constructor-arg>
<!--复杂数据类型的注入=====》数组-->
<property name="MYArray" >
<array>
<value>德国</value>
<value>日本</value>
<value>美国</value>
</array>
</property>
<!--复杂数据类型的注入=====》List-->
<property name="myList">
<list>
<value>高合HIFI</value>
<value>塞力斯</value>
<value>哪吒</value>
</list>
</property>
<!--复杂数据类型的注入=====Map-->
<property name="myMap">
<map>
<entry key="华为" value="任正非"></entry>
<entry key="阿里巴巴" value="何勇"></entry>
<entry key="360" value="红衣大叔"></entry>
</map>
</property>
<!--复杂数据类型的注入=====》set-->
<property name="mySet">
<set>
<value>篮球</value>
<value>羽毛球</value>
<value>保龄球</value>
</set>
</property>
<!--复杂数据类型的注入=====》properties键值对数据-->
<property name="prpp">
<props>
<prop key="塞力斯">问界</prop>
<prop key="长安">阿维塔</prop>
<prop key="比亚迪">仰望U9</prop>
</props>
</property>
</bean>
Bean的实例化三种方式:
默认无参构造
必须保持无参构造方法的存在
bean的实例化(无参构造方法)《默认》
<bean id="book" class="com.apesource.pojo.Book"></bean>
工厂方法实例化
创建BeansFactory:
package com.apesource.factory;
import com.apesource.pojo.Book;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/**
* @author 闫亚东
* @version 1.0
* @since 2024/7/15
*/
public class BeansFactory {
public static Object getBean() {
Properties properties = new Properties();
InputStream stream = BeansFactory.class.getClassLoader().getResourceAsStream("Beans.properties");
try {
properties.load(stream);
String value = properties.getProperty("");
return Class.forName(value).newInstance();
} catch (IOException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
}
配置文件注入对象:
<bean id="book1" class="com.apesource.pojo.Book" factory-bean="factory" factory-method="getBean"></bean>
<bean id="factory" class="com.apesource.factory.BeansFactory"></bean>
静态工厂实例化
<!--bean的实例化(static工厂方法)-->
<bean id="book1" class="com.apesource.factory.BeansFactory" factory-method="getBean"></bean>
<bean id="book1" class="com.apesource.pojo.Book" init-method="doinit" destroy-method="dodestroy">
<property name="name" value="闫亚东"></property>
</bean>
三.springAOP(面向切面)
AOP 为 Aspect Oriented Programming 的缩写,意思为面向切面编程,
是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术
AOP 是 OOP 的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,
是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得
业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
AOP 的作用及其优势
作用:在程序运行期间,在不修改源码的情况下对方法进行功能增强
优势:减少重复代码,提高开发效率,并且便于维护
AOP 的应用
1.日志
2.事务
3.权限
Spring AOP 基于动态代理实现:
○ 如果被代理的对象,已经实现某个接口,则 Spring AOP 会使用 JDK Proxy(反射),基于接口的方式,创建代理对象(JDK动态代理的核心是InvocationHandler接口和Proxy类);
○ 如果被代理的对象,没有实现某个接口,就无法使用 JDK Proxy 去进行代理了,这时候 Spring AOP 会使用 Cglib,基于继承的方式,生成一个被代理对象的子类来作为代理(Cglib动态代理的核心是MethodInterceptor接口和Enhancer类);
AOP术语:
AOP通知类型
AOP将抽取出来的共性功能称为通知;通知类型:以通知在上下文中的具体位置作为划分
前置通知(Before)
后置通知(After)
返回通知(After-returning)
异常通知(After-throwing)
环绕通知(Around)
AOP连接点(Join point)
AOP将所有的方法都视为连接点,不管是接口里面的抽象方法,还是实现类里面的重写方法,都是连接点
AOP切点(Pointcut)
AOP将可能被抽取共性功能的方法称为切入点。切入点是连接点的子集
AOP目标对象(Target): 就是挖掉功能的方法对应的类生的对象,这种对象是无法直接完成最终工作的
AOP织入(Weaving):就是将挖掉的功能回填的动态过程
AOP切面:切点+通知
实现步骤:
1.添加依赖,aop与aspectj表达式的依赖
2.创建spring的主配置文件,bean内的命名空间要添加aop的
3.创建业务代码并编写日志记录代码(事务管理代码)
4.将业务层与日志记录层注入spring容器
5.<aop:config>--aop配置
aop:aspect--aop切面
aop:before--通知内容与通知类型
切点表达式配置语法:
execution(修饰符 返回值 包名称.类名称.方法名称(参数列表))
eg:
execution(public void com.apesource.service.ServiceImp.findAll())
1.修饰符可以省略代表任意
execution(返回值 包名称.类名称.方法名称(参数列表))
2.返回值可以使用“*”代表任意
execution(* 包名称.类名称.方法名称(参数列表))
3.包名可以使用“*”代表任意名称
execution(* *.*.*.类名称.方法名称(参数列表))
4.包名可以使用“..”代表任意个数
execution(* *...类名称.方法名称(参数列表))
5.类名与方法名可以使用“*”代表任意
execution(* *...*.*(参数列表))
6.参数列表可以使用".."代表任意个数任意类型
execution(* *...*.*(..))
如果有参数
int======>int
String===>java.lang.String
<aop:config>
<!--切面-->
<aop:aspect id="idaspect" ref="logger">
<!--切点-->
<aop:pointcut id="point" expression="execution(* *..*.*(..))"/>
<!--通知-->
<!-- <aop:before method="beforeMethod" pointcut-ref="point"></aop:before>
<aop:after-returning method="returnMethod" pointcut-ref="point"></aop:after-returning>
<aop:after-throwing method="throwMethod" pointcut-ref="point"></aop:after-throwing>
<aop:after method="afterMethod" pointcut-ref="point"></aop:after>-->
<aop:around method="around" pointcut-ref="point"></aop:around>
</aop:aspect>
</aop:config>
注解随后再议