关于Spring知识点的小结
程序员文章站
2022-03-14 10:29:07
...
知识点一
- Spring致力于提供一种方式去管理下项目中的所有对象,塔式分层的javase/ee应用(一站式)full-stack的轻量级开源框架。为什么这么说呢?主要是因为①作用于各个层,②整合第三方优秀框架.
- 接下来,说下spring的体系结构.:五部分包括核心容器.aop,text,web,dao等.
- spring IOC的底层原理就是:工厂设计模式+配置文件+反射机制来解决代码与代码(类与类)之间的耦合.
- IOC 控制反转:本该由程序创建new 创建的对象,现在把权力给了spring,通过DI依赖注入,解决了对象与对象之间的依赖关系.
知识点二
创建bean的三种方式:
第一步:导约束
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--创建Bean的三种方式 -->
<!-- 第一种方式:使用默认构造函数创建。
在spring的配置文件中使用bean标签,配以id和class属性之后,且没有其他属性和标签时。
采用的就是默认构造函数创建bean对象,此时如果类中没有默认构造函数,则对象无法创建。
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"></bean>
-->
<!-- 第二种方式: 使用普通工厂中的方法创建对象(使用某个类中的方法创建对象,并存入spring容器)
<bean id="instanceFactory" class="com.itheima.factory.InstanceFactory"></bean>
<bean id="accountService" factory-bean="instanceFactory" factory-method="getAccountService"></bean>
-->
<!-- 第三种方式:使用工厂中的静态方法创建对象(使用某个类中的静态方法创建对象,并存入spring容器)
<bean id="accountService" class="com.itheima.factory.StaticFactory" factory-method="getAccountService"></bean>
-->
<!-- bean对象的生命周期
单例对象
出生:当容器创建时对象出生
活着:只要容器还在,对象一直活着
死亡:容器销毁,对象消亡
总结:单例对象的生命周期和容器相同
多例对象
出生:当我们使用对象时spring框架为我们创建
活着:对象只要是在使用过程中就一直活着。
死亡:当对象长时间不用,且没有别的对象引用时,由Java的垃圾回收器回收
-->
</beans>
- 如果是自己写的类,使用无参构造
- 如过是其他jar包,没有提供无参构造,需要模拟一个工厂类,工厂中普通成员方法创建对象
- 工厂中静态方法创建对象
知识点三
DI:依赖注入
依赖注入解决对象与对象之间的依赖关系
- 类中的构造函数,类中需要提供一个对应参数列表的构造函数
- setter,类中提供需要注入成员的 set 方法
- 注解
知识点四
基于注解的 IOC 配置
- 拷贝jar包
- 导入约束
基于注解整合时,导入约束时需要多导入一个 context 名称空间下的约束
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 告知 spring 创建容器时要扫描的包 -->
...
</beans>
常用一些注解
-
@Component作用:(@Controller @Service @Repository)
把资源让 spring 来管理。相当于在 xml 中配置一个 bean。
属性:
value:指定 bean 的 id。如果不指定 value 属性,默认 bean 的 id 是当前类的类名。首字母小写。 - @aaa@qq.com@Resource
-
@Value作用:
注入基本数据类型和 String 类型数据的
属性:
value:用于指定值 -
@Scope作用:
指定 bean 的作用范围。
属性:
value:指定范围的值。
取值:singleton prototype request session globalsession - 注解的优势:
配置简单,维护方便(我们找到类,就相当于找到了对应的配置)。
XML 的优势:
修改时,不用改源码。不涉及重新编译和部署。
Spring 管理 Bean 方式的比较:
知识点五
Spring AOP
讲AOP之前,先回忆下servlet
- servlet的生命周期,servlet在Tomact服务器中是一个单实例,多线程的对象.①我们部署的项目一发布当第一个用户访问的时候,就会创建serlet,其他用户再次访问,就不会再创建了,创建时会调用init方法.②当有用户访问,servlet都会开启一个子线程去调用service方法.③正常关闭,会调用destroy方法销毁servlet.接下来会用ThreadLocal<Connection>,底层是一个map,让key保存当前线程,value保存connnectioon,能起到一个线程和连接引用的关系,从而保证我们的连接唯一.(每个方法都要被事物管理)
我们说sevrlet是一个小程序,服务器一启动,xml文件加载,Tomact--运行在jvm中,servlet运行在Tomact中!
- 以上会造成我们的事物代码和service代码的耦合,所有AOP解决的就是业务逻辑和业务逻辑的耦合,底层使用的是动态代理.
动态代理两种方式:
jdk动态代理对象和原始对象是兄弟关系,只能针对接口产生代理,也就是说代理的对象必须实现一个接口.
/**
* 用于创建Service的代理对象的工厂
*/
public class BeanFactory {
private IAccountService accountService;
private TransactionManager txManager;
public void setTxManager(TransactionManager txManager) {
this.txManager = txManager;
}
public final void setAccountService(IAccountService accountService) {
this.accountService = accountService;
}
/**
* 获取Service代理对象
* @return
*/
public IAccountService getAccountService() {
return (IAccountService)Proxy.newProxyInstance(accountService.getClass().getClassLoader(),
accountService.getClass().getInterfaces(),
new InvocationHandler() {
/**
* 添加事务的支持
*
* @param proxy
* @param method
* @param args
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if("test".equals(method.getName())){
return method.invoke(accountService,args);
}
Object rtValue = null;
try {
//1.开启事务
txManager.beginTransaction();
//2.执行操作
rtValue = method.invoke(accountService, args);
//3.提交事务
txManager.commit();
//4.返回结果
return rtValue;
} catch (Exception e) {
//5.回滚操作
txManager.rollback();
throw new RuntimeException(e);
} finally {
//6.释放连接
txManager.release();
}
}
});
}
}
CGLIB代理的对象,不管目标类有没有实现接口,产生的代理对象和原始对象是子父类关系,原始类是不能被final修饰.
/**
* 模拟一个消费者
*/
public class Client {
public static void main(String[] args) {
final Producer producer = new Producer();
/**
* 动态代理:
* 特点:字节码随用随创建,随用随加载
* 作用:不修改源码的基础上对方法增强
* 分类:
* 基于接口的动态代理
* 基于子类的动态代理
* 基于子类的动态代理:
* 涉及的类:Enhancer
* 提供者:第三方cglib库
* 如何创建代理对象:
* 使用Enhancer类中的create方法
* 创建代理对象的要求:
* 被代理类不能是最终类
* create方法的参数:
* Class:字节码
* 它是用于指定被代理对象的字节码。
*
* Callback:用于提供增强的代码
* 它是让我们写如何代理。我们一般都是些一个该接口的实现类,通常情况下都是匿名内部类,但不是必须的。
* 此接口的实现类都是谁用谁写。
* 我们一般写的都是该接口的子接口实现类:MethodInterceptor
*/
Producer cglibProducer = (Producer)Enhancer.create(producer.getClass(), new MethodInterceptor() {
/**
* 执行北地阿里对象的任何方法都会经过该方法
* @param proxy
* @param method
* @param args
* 以上三个参数和基于接口的动态代理中invoke方法的参数是一样的
* @param methodProxy :当前执行方法的代理对象
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
//提供增强的代码
Object returnValue = null;
//1.获取方法执行的参数
Float money = (Float)args[0];
//2.判断当前方法是不是销售
if("saleProduct".equals(method.getName())) {
returnValue = method.invoke(producer, money*0.8f);
}
return returnValue;
}
});
cglibProducer.saleProduct(12000f);
}
}
知识点6
配置AOP 的两种方式 xml和注解
知识点7
spring实现事物控制
上一篇: Mybatis----参数传递
下一篇: JSF框架整理(一)