多态:一个父类/接口的引用可以执行其任何一个子类/实现类的对象。
问题: 在Servlet中需要调用Service中的方法,则需要在Servlet类中通过使用new关键字创建Service 的实例对象;在Service实现类中需要调用DAO中的方法,也需要在Service实现类中通过new关键字创建DAO实现类对象。这增加了代码的耦合性、失去了面向接口编程的灵活性。解决方案: 面向接口编程。在Service中定义Service接口的对象变量,不适用new关键字创建实现类对象,在servlet的实例化的时候,通过反射动态的给Service对象变量赋值。
如何实现: Spring可以实现。
Spring是一个轻量级的控制反转(IoC)和 面向切面(AOP)的容器框架。用途:用来解决企业项目开发的复杂度问题——解耦。
特征:
事务的管理操作
。Spring的生态体系:
Spring Framework:IoC、AOP。核心框架。
Spring Boot:工具框架
Spring Data:Spring提供的数据访问的客户端。(比如访问数据库会用到jpa)
Spring Cloud:微服务架构
Spring Security:安全框架
什么事持久层?
答:可以理解成数据 保存在 数据库或者硬盘一类可以保存很长时间的设备里面,不像放在内存中那样断电就消失了,也就是把数据存在持久化设备上,mybatis就是持久层。
Spring IOC容器组件,可以完成对象的创建、对象属性赋值、对象管理。
步骤如下:
Java项目
使用也可以在Web项目
**使用core、beans、expression
、context
(导入context其他四个也会默认导入))+aop
applicationContext.xml
的文件名(可自定义)使用Spring IoC创建对象并管理对象
步骤如下:
applicationContext.xml
ClassPathXMLApplicationContext context = new ClassPathXMLApplicationContext("applicationContext.xml");
Spring容器加载配置文件之后,通过反射创建类的对象,并给属性赋值;
在bean标签中通过配置property
属性的方式,给属性赋值。(配置property实际上就是通过反射调用set方法给属性赋值,完成属性的注入,所以要求必须得有set方法才行)
(1)简单类型(int、float、double)以及字符串 :直接通过property
标签的value
属性赋值
在这里插入代码片
(2)日期对象 :方式1:在property
标签中通过ref
引用Spring容器中的一个对象;方式2:在property标签中添加字标签bean
来指定对象
在这里插入代码片
(3)自定义类对象属性 :方式1:在property
标签中通过ref
引用Spring容器中的一个对象;方式2:在property标签中添加字标签bean
来指定对象
在这里插入代码片
(4)集合类型 :
a)List:List中的元素是字符串或简单类型的封装,直接赋值;List中的元素使对象类型,则在list标签内加上bean
的子标签,或者加上ref
引用现有容器中的bean
即可
b)Set:与List元素的注入方式相同
c)Map:
<property name="maps">
<map>
<entry>
<key>
<value>k1</value>
</key>
<value>abc</value>
</entry>
<entry>
<key>
<value>k2</value>
</key>
<value>def</value>
</entry>
</map>
</property>
(1)简单类型、字符串类型、对象类型:
(2)集合类型属性:
在bean标签中可以用过scope
属性指定对象的作用域:
scope="singleton"
:表示当前bean
是单例模式。(且默认是饿汉模式,即Spring容器初始化阶段就会完成此对象的创建;当在bean
标签中设置lazy-init="true"
则会变为懒汉模式,什么时候要这个对象什么时候才会创建)每次通过Spring容器获取此bean的对象时都是同一个对象。scope="prototype"
:表示当前bean为非单例模式,即多例模式。每次通过Spring容器获取此bean的对象时都会创建一个新的对象。在bean标签中通过init-method属性指定当前bean的初始化方法,初始化方法在构造器执行之后执行;
通过destroy-method属性指定当前bean的销毁方法,销毁方法在对象销毁之前执行。
具体功能在开发中需要根据具体的业务需求进行操作。
public class Book{
private int bookId;
private String bookName;
//初始化方法:在创建当前类对象时调用的方法,进行一些资源准备的操作
public void init(){
// 函数内容
}
//销毁方法:在Spring容器销毁对象时调用此方法,进行一些资源回收性的操作
public void destroy(){
// 函数内容
}
}
<bean id="book" class="com.qfedu.ioc.bean.Book" scope="prototype" init-method="init" destroy-method="destroy">
bean>
autowire
byName
:根据当前Bean的属性名在Spring 容器中寻找匹配的对象,如果根据name找到了bean但是类型不匹配则会抛出异常byType
:根据当前Bean的属性类型在Spring容器中寻找匹配的对象,如果根据类型找到了多个bean也会抛出异常【图】
Spring IOC的使用,需要我们通过XML将类声明给Spring容器进行管理,从而通过Spring工厂完成对象的创建及属性值的注入;
Spring除了提供基于XML的配置方式,同时提供了基于注解的配置:即直接在实体类中添加注解声明给Spring容器管理,以简化开发步骤;
步骤如下:
pom.xml
配置文件里添加依赖
applicationContext.xml
在applicationContext.xml声明Spring的扫描范围
,已达到Spring初始化时扫描带有注解的实体类并完成初始化工作@Component
@Component(value="stu")
可以通过value属性用于指定当前bean的id,相当于bean标签的id属性,value属性也可省略,若省略则默认当前类的id为类名首字母改小写@Controller
注解主要声明将控制器类配置给Spring管理,比如Servlet@Service
注解主要声明业务处理类配置Spring管理,Service接口的实现类@Repository
主要声明持久化类配置给Spring管理,比如DAO接口@Component
除了控制器、service和DAO之外的类一律使用此注解声明@Scope
@Scope
注解:用于声明当前类是单例模式还是非单例模式,相当于bean标签的scope属性,默认是单例模式@Scope("prototype")
:声明当前类是非单例模式@Lazy
@Lazy
:类注解,用于声明一个单例模式的Bean是否为懒汉模式,默认为true懒汉模式@Lazy(false)
:声明当前类是恶汉模式@PostConstruct
与@PreDestory
@PostConstruct
:方法注解,声明一个方法为当前类的初始化方法(在构造器之后执行),相当于bean标签的init-method
属性@PreDestory
:方法注解,声明一个方法为当前类的销毁方法(在对象从容器中释放之前执行),相当于bean标签的destory-method
属性@Autowired
@Autowired(required=false)
通过required
属性配置当前自动装配的对象是否是必须的,false
就表示非必须@Qualifier("clazz")
:放到参数的set方法的参数引用括号里,表明其属性的set是按照这个名字去取的@Autowired
public void setClazz(@Qualifier("c2") Clazz clazz){
this.clazz = clazz;
}
@Resource
代理设计模式的优点:将通用性的工作都交给代理对象完成,被代理对象只需专注自己的核心业务
- 创建一个类,实现InvocationHandler接口,重写invoke方法
- 在类中定义一个Object类型的变量,并提供这个变量的有参构造器,用于将被代理对象传递进来
- 定义getProxy方法,用于创建并返回代理对象
- 添加cglib的依赖
<!-- https://mvnrepository.com/artifact/cglib/cglib --> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.3.0</version> </dependency>
- 创建一个类,实现
MethodInterceptor
接口,同时实现接口中的intercept
方法- 在类中定义一个Object类型的变量,并提供这个变量的有参构造器,用于传递被代理对象
- 定义
getProxy
方法创建并返回代理对象(代理对象是通过创建被代理类的自雷来创建的)
Aspect Oriented Programming 面向切面编程,是一种利用“横切”的技术(底层实现就是动态代理),对原有的业务逻辑进行拦截,并且可以再这个拦截的横切面上添加特定的业务逻辑,对原有的业务进行增强。
基于动态代理实现在不改变原有业务的情况下对业务逻辑进行增强。
连接点:程序中的所有方法都是连接点
切入点:被Spring横切的方法
切点:添加到切入点的新增的业务方法
切面:就是定义切点方法的类
通过配置来告诉Spring AOP需要将切点放到切入点的位置
在DAO的方法添加开启事务和提交事务的逻辑
AOP开发步骤:
注意:
如果要使用Spring aop面向切面编程,调用切入点的方法的对象必须通过Spring容器获取;
如果一个类中的方法被声明为切入点并且织入了切入点之后,通过Spring容器获取该类对象,实则获取到的是一个代理对象;
如果一个类中的方法没有被声明为切入点,通过Spring容器获取的就是这个类真实创建的对象
各种切入点的声明方式:
(待更新)
AOP使用注意事项:
(待更新)