Spring知识点总结(阶段性)

目录

DI和IOC的区别 

由IOC的引伸:Bean是如何注册到IOC容器的

重点:容器启动阶段

AOP的理解

AOP中的几个名词:

 BeanFactory和ApplicationContext有什么区别?

Spring中bean的作用域

关于Spring框架Bean的安全问题

xml中注入bean的几种方式

Spring事务

总结:Spring用到的设计模式


DI和IOC的区别 

共同目标:获取外部资源;

DI:依赖注入,是从应用角度考虑的,利用容器获得外部资源

依赖注入的依赖不是指的应用程序依赖ioc容器,而是容器在创建bean时注入的这些依赖项(依赖项:与之一起工作的其他对象,比如当前类包含其他类的属性)

IOC:是从容器角度考虑的,创建对象/获取对象的权利由用户变为容器;

其实IOC的原理就是:工厂模式+反射机制


由IOC的引伸:Bean是如何注册到IOC容器的

首先IOC作用:将外部资源的创建权利给到容器——>以便于对象实例的创建与使用分离;

当业务中需要依赖某个对象时,直接问Spring要即可(这个容器其实也就是起到一个代理作用)

被动而这个对象的生命周期不再是由引用它的对象决定的了,而是spring容器决定的了,Spring容器帮助创建查找注入依赖对象,而之前的引用它的对象就变成了接受

(9条消息) 静态代理与动态代理的思考_Fairy要carry的博客-CSDN博客

当对象创建的任务给到了Spring容器,那么Spring容器需要知道创建一个对象的一些必要信息(xml配置文件中,一般咱们用注解,然后xml配置扫描即可)

<bean id="role" class="com.wbg.springxmlbean.entity.Role">
    <!-- property元素是定义类的属性,name属性定义的是属性名称 value是值
    相当于:
    Role role=new Role();
    role.setId(1);
    role.setRoleName("高级工程师");
    role.setNote("重要人员");-->
    <property name="id" value="1"/>
    <property name="roleName" value="高级工程师"/>
    <property name="note" value="重要人员"/>
</bean>
   <context:component-scan base-package="com.yanzhen.service" />

重点:容器启动阶段

首先知道的是,Java中万物皆对象,所有程序代码注解、xml啥的等配置元信息,在内存中都需要以一种对象的形式表示;这里我们只需要知道配置元信息被加载到内存之后是以BeanDefination的形存在的即可。

那么问题来了,Spring是怎么看懂这些配置元信息的(或者说如何加载成BeanDefination)?

这里用的就是BeanDefinationReader加载配置元信息,将其转为内存形式的Beandefination

引出问题,既然BeanDefination已经有了,那么我们怎么获得他呢?

这里通过Bean定义的id到对象的BeanDefination的对应关系,所以说要获取他,需要BeanDefinationRegistry——>可以理解为一个map(里面是BeanDefination,键值对形式,键为:id)

BeanFactoryPostProcessor(还不很理解,感觉没啥大用):

BeanFactoryPostProcessor是容器启动阶段Spring提供的一个扩展点,主要负责对注册到BeanDefinationRegistry中的一个个的BeanDefination进行一定程度上的修改与替换。例如我们的配置元信息中有些可能会修改的配置信息散落到各处,不够灵活,修改相应配置的时候比较麻烦,这时我们可以使用占位符的方式来配置。例如配置Jdbc的DataSource连接的时候可以这样配置:

<bean id="dataSource"  
    class="org.apache.commons.dbcp.BasicDataSource"  
    destroy-method="close">  
    <property name="maxIdle" value="${jdbc.maxIdle}"></property>  
    <property name="maxActive" value="${jdbc.maxActive}"></property>  
    <property name="maxWait" value="${jdbc.maxWait}"></property>  
    <property name="minIdle" value="${jdbc.minIdle}"></property>  
  
    <property name="driverClassName"  
        value="${jdbc.driverClassName}">  
    </property>  
    <property name="url" value="${jdbc.url}"></property>  
  
    <property name="username" value="${jdbc.username}"></property>  
    <property name="password" value="${jdbc.password}"></property>  
</bean> 


AOP的理解

 简而言之,就是不动原来的代码,在此基础上增加业务功能,有利于降低耦合度,提高维护性;

利用代理模式(这里感觉可以用适配器模式,如果是单独增加一个业务,当然,如果有作用范围,切面那是必然的)

主要是以动态代理:运行时产生,减少维护;

AOP中的几个名词:

 <!--注册bean-->
    <bean id="userService" class="com.huang.service.UserServiceImpl"/>
    <bean id="BeforeLog" class="com.huang.log.BeforeLog"/>
    <bean id="afterLog" class="com.huang.log.AfterLog"/>

第一种: 

 <aop:config>
                <!--切入点 expression:表达式,execution(要执行的位置!* * * * *)-->
                <aop:pointcut id="pointcut" expression="execution(* com.huang.service.UserServiceImpl.*(..))"/>
                <!--执行环绕增加!-->
                <aop:advisor advice-ref="beforelog" pointcut-ref="pointcut"/>
                <aop:advisor advice-ref="afterlog" pointcut-ref="pointcut"/>
            </aop:config>

第二种:

 <bean id="diy" class="com.huang.diy.DiyPointCut"/>
    <aop:config>
<!--    首先定义一个切面类    -->
        <aop:aspect ref="diy">
<!--  切面类切入的地方:也就是切入点-->
            <aop:pointcut id="pointcut" expression="execution(* com.huang.service.UserServiceImpl.*(..))"/>
<!--  切面类里面的方法:也就是通知-->
            <aop:before method="before" pointcut-ref="pointcut"/>
            <aop:after method="after" pointcut-ref="pointcut"/>
        </aop:aspect>
    </aop:config>

第三种:

<aop:aspectj-autoproxy/>
package com.huang.diy;
 
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.BeforeAdvice;
import org.springframework.aop.MethodBeforeAdvice;
 
import java.lang.reflect.Method;
 
//注解实现aop
@Aspect
public class AnnotationPointCut implements AfterReturningAdvice , MethodBeforeAdvice {
    @Before("execution(* com.huang.service.UserServiceImpl.*(..))")
    public void before() {
        System.out.println("方法前执行1");
    }
 
    @After("execution(* com.huang.service.UserServiceImpl.*(..))")
    public void after() {
        System.out.println("方法后执行1");
    }
 
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("执行的结果为:"+method.getName()+"方法");
    }
 
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println(target.getClass()+"的"+method.getName()+"要被执行");
    }
 
//    @Around("execution(* com.huang.service.UserServiceImpl.*(..))")
//    public void around(ProceedingJoinPoint jp) throws Throwable {
//        System.out.println("环绕前");
//        System.out.println("签名:" + jp.getSignature());
//        //执行目标方法proceed
//        Object proceed = jp.proceed();
//        System.out.println("环绕后");
//        System.out.println(proceed);
//    }
 
}

 BeanFactory和ApplicationContext有什么区别?

都可以作为Spring容器;

BeanFactory:最底层接口,IOC核心,定义了它的基本功能:Bean的顶柜加载,实例化;

并且它是采用来加在的方式来注入Bean的,只有你需要的时候才会有;

ApplicationContext:容器一启动,一次性创建了所有的Bean,有利于检查,不过速度较慢;

并且还扩展了其他功能:国际化...

Spring中bean的作用域

singleton:单例bean,采用单例模式,所以说所有线程拿到的都是同一个对象,速度较快,加载过,后面线程请求的话就不需要再创建了;

 (9条消息) 单例模式的思考_Fairy要carry的博客-CSDN博客

prototype:每一个bean请求都会创建一个新的实例,这样加载会较慢,但是安全,毕竟每个线程拿到的都是不一样的;

 request:每一个request请求都会创建一个实例,但是request请求之后,bean就会失效,被回收;

session:一次会话共享一次实例;


关于Spring框架Bean的安全问题

这里我们需要结合上面的作用域考虑

1、prototype:每次都是一个新对象,所以线程之间对于bean对象是不共享的,安全

2、Singleton:之前我们分析了,安全问题肯定存在的,但是如果Bean是一个无状态的Bean,也就是说线程的操作不会对这个Bean产生影响,那么这个Bean是就是线程安全的,比如Controller类、Service、Dao这些Bean大多都是无状态的,只关注方法本身;

有状态Bean(Stateful Bean) :就是有实例变量的对象,可以保存数据,是非线程安全的。

无状态Bean(Stateless Bean):就是没有实例变量的对象,不能保存数据,是不变类,是线程安全的。

如果是有状态的话,我们上锁就行或者改作用域改为prototype,上锁比如synchronized;

我们可以采用空间换时间的方式,因为每个线程都有独立的变量副本,所以我们可以为每个线程提供一个独立的变量副本,synchronized(变量),这样就互不干扰了,但是当线程量巨大时,这种方法GG;


xml中注入bean的几种方式

set方式,构造器方式,静态工厂,实例工厂这四种; 

 (9条消息) Spring中bean的注入方式_张维鹏的博客-CSDN博客_spring注入bean的方式
(34条消息) 总结 Spring 注入 bean 的四种方式_一支帆的博客-CSDN博客_spring注入bean的几种方式


Spring事务

(9条消息) Spring事务_Fairy要carry的博客-CSDN博客


总结:Spring用到的设计模式

工厂模式:使用BeanFactory和ApplicationContet来创建对象,IOC中也有用到

单例模式:Bean的默认作用域

代理模式:AOP使用动态代理(**)

适配器模式:增强一个新的功能而不改变原有代码(老接口不变,老的业务功能也不变)

(9条消息) 代理模式-装饰器模式-适配器模式_Fairy要carry的博客-CSDN博客

模板方法:将相同的代码放到父类,不同的放到子类——>解决代码冗余

以下不了解

桥接模式:可以根据客户的需求能够动态切换不同的数据源。比如我们的项目需要连接多个数据库,客户在每次访问中根据需要会去访问不同的数据库

观察者模式:Spring事件驱动模型就是观察者模式的一个经典应用。

策略模式:例如Resource的实现类,针对不同的资源文件,实现了不同方式的资源获取策略

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Fairy要carry

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值