spring

一、Spring是什么?

对于面试者回答什么是Spring,这个问题占6分分值,分值点分布:
1、Spring的核心是一个轻量级(Lightweight)的容器(Container)。
2、Spring是实现IoC(Inversion of Control)容器和非入侵性(No intrusive)的框架。
3、Spring提供AOP(Aspect-oriented programming)概念的实现方式。
4、Spring提供对持久层(Persistence)、事物(Transcation)的支持。
5、Spring供MVC Web框架的实现,并对一些常用的企业服务API(Application Interface)提供一致的模型封装。
6、Spring提供了对现存的各种框架(Structs、JSF、Hibernate、Ibatis、Webwork等)相整合的方案。
总之,Spring是一个全方位的应用程序框架。

Spring框架主要由七部分组成,分别是 Spring Core、 Spring AOP、 Spring ORM、 Spring DAO、Spring Context、 Spring Web和 Spring Web MVC。

## Spring优点

1.方便解耦,简化开发
通过Spring提供的IoC容器,我们可以将对象之间的依赖关系交由Spring进行控制,避免硬编码所
造成的过度程序耦合。有了Spring,用户不必再为单实例模式类、属性文件解析等这些很底层的需
求编写代码,可以更专注于上层的应用。
2.AOP编程的支持
通过Spring提供的AOP功能,方便进行面向切面的编程,许多不容易用传统OOP实现的功能可以通过
AOP轻松应付。
3.声明事物的支持
在Spring中,我们可以从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的
管理,提高开发效率和质量。
4.方便程序的测试
可以用非容器依赖的编程方式进行几乎所有的测试工作,在Spring里,测试不再是昂贵的操作,
而是随手可做的事情。例如:Spring对Junit4支持,可以通过注解方便的测试Spring程序。
5.方便集成各种优秀框架
Spring不排斥各种优秀的开源框架,相反,Spring可以降低各种框架的使用难度,Spring提供了
对各种优秀框架(如Struts,Hibernate、Hessian、Quartz)等的直接支持。
6.降低Java EE API的使用难度
Spring对很多难用的Java EE API(如JDBC,JavaMail,远程调用等)提供了一个薄薄的封装层,
通过Spring的简易封装,这些Java EE API的使用难度大为降低。

二、使用步骤

1.导包

commons-logging-1.2.jar
spring-core-4.3.6.RELEASE.jar
spring-context-4.3.6.RELEASE.jar
spring-beans-4.3.6.RELEASE.jar
spring-expression-4.3.6.RELEASE.jar

2.编写xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans  xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-4.3.xsd">
    <bean id="userdaoim" class="main.java.userdaoim"/>
</beans>

3.调用Spring的核心容器

Spring框架主要是通过其核心容器来实现:
BeanFactory
ApplicationContext为前者的子接口,额外添加了对国际化,资源访问,事件传播等方面的支持

ApplicationContext两种创建方式:
1.ClassPathXmlApplicationContext

从类路径中寻找

 ApplicationContext app = new ClassPathXmlApplicationContext("/resourse/applicationContext.xml");
2.FileSystemXmlApplicationContext

从绝对路径中寻找

 new FileSystemXmlApplicationContext()
获取bean
app.getBean(beanid); 需要转型
app.getBean(beanid.class)

三、依赖注入(SpringIoc)

依赖注入和控制反转含义相同,只不过这两个称呼是从不同的角度来叙述同一个概念

控制反转:当调用者需要java对象时,通常会new 一个,但使用spring容器之后,spring容器会负责控制程序之间的关系,控制权由应用代码转移到了spring容器,控制权发生了反转。

依赖注入:从spring容器来看,spring容器负责将依赖对象赋值给调用者的成员变量,这相当于为调用者注入了它的依赖实例

实现方式

set注入

1.配置xml
2.被注入的属性,需要实现set方法

   private String name;
    public void setName(String name) {//配置文件使用property的前提
        this.name = name;
    }

构造器注入

配置xml
既然要注入那么就是有参构造函数


四、Bean

Bean实例化

构造器实例化

默认无参方式实例化
1.一个有无参构造器的类
2.配置bean
3.通过容器调用

静态工厂实例化

1.一个工厂类包含一个静态的返回一个所需对象类型的方法
2.配置工厂类的bean,factory-method=“静态方法名”

<bean id="user2" class="org.sang.User2Factory" factory-method="getInstance"/>

实例工厂实例化

1.一个工厂类,只是原来方法不是静态的
2.配置工厂类bean
3.再配置y一个bean
facotry-bean—>该工厂类
factory-method–>该方法

<bean class="org.sang.User3Factory" id="user3Factory"/>
    <bean id="user3" factory-bean="user3Factory" factory-method="getUser3"/>

Bean作用域

作用域名称说明
singleton (默认的)在每个Spring IoC容器中,一个bean定义对应只会有唯一的一个bean实例。
prototype一个bean定义可以有多个bean实例。
request一个bean定义对应于单个HTTP 请求的生命周期。也就是说,每个HTTP 请求都有一个bean实例,且该实例仅在这个HTTP 请求的生命周期里有效。该作用域仅适用于WebApplicationContext环境。
session一个bean 定义对应于单个HTTP Session 的生命周期,也就是说,每个HTTP Session 都有一个bean实例,且该实例仅在这个HTTP Session 的生命周期里有效。该作用域仅适用于WebApplicationContext环境。
application一个bean 定义对应于单个ServletContext 的生命周期。该作用域仅适用于WebApplicationContext环境。
websocket一个bean 定义对应于单个websocket 的生命周期。该作用域仅适用于WebApplicationContext环境。
globalSession在一个全局的HTTP Session ,容器会返回同一个实例,仅限于使用portlet上下文时有效

Portlet规范定义了全局Session的概念,它被所有构成某个 portlet web应用的各种不同的portlet所共享。

Bean生命周期

简单点说就是:bean的实例化–>bean的初始化–>bean的使用–>bean的销毁
1.实例化:也就是new一个对象
2.属性注入:Spring上下文对实例化的bean进行配置(IOC注入)
3.设置beanId:如果实现BeanNameAware接口,调用setBeanName()方法设置ID
4.调用BeanFactoryAware.setBeanFactory(setBeanFactory(BeanFactory):可以用这个方式来获取其它Bean,只需在Spring配置文件中配置一个普通的Bean就可以;
5.调用ApplicationContextAware.setApplicationContext(ApplicationContext):与BeanFactoryAware.setBeanFactory同样作用,但是ApplicationContextAware是子接口,可以实现更多接口;
6.实例化之前调用:BeanPostProcessor.postProcessBeforeInitialization(Object obj, String s)方法调用,
7.实例化:如果在spring配置中还配置了init-method属性,会自动调用该方法;
8.实质化之后调用:如果关联BeanPostProcessor接口,调用postProcessAfterInitialization(Object obj, String s)方法,
注:前面这里我们就完成bean的实例化;
9.bean的销毁:当bean不再被使用时,就会调用destroy()方法;
10.bean销毁调用方法:如果配置了destroy-method方法,会自动调用该方法;
————————————————
版权声明:本文为CSDN博主「Rick1024」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/keenstyle/article/details/104820909

Bean的装配

无外乎就是注入bean,配置bean

xml

set注入

条件:
1.bean类提供一个无参构造器
2.注入的属性具有set方法

 <bean id="student" class="com.ius.demo.Student" lazy-init="true"  >
     <property name="tTT" value="东东" >< /property >
  </bean >
构造注入

条件:
1.提供带有参数的有参构造方法

 <bean id="student" class="com.ius.demo.Student" lazy-init="true" scope="singleton" >
     <constructor-arg index="0" value="tom"/>
     <constructor-arg index="1" >
     <list>
     <value>"list1"</value>
      <value>"list2"</value>
     </list>
     </constructor-arg>
  </bean >

注解

优点:不用在xml为每个bean配置id.calss
直接通过扫描包注解即可,包扫描需要导包(spring-aop-4.36…jar)
(1)@Repository   一般用于数据访问(数据访问(持久)层组件,实现dao访问)
(2)@Service    一般用于服务(业务层组件,处理业务逻辑,比如注入并操作dao)
(3)@Controller    一般用于控制器(控制层组件)
(4)@Component    一般用于自定义组件,把普通类实例化到spring容器中,相当于配置文件中的
(5)@Autowired 根据类型   基本等价于 @Resource(name=“”)

1.配置bean
@Service("userdaoim")
public class userdaoim implements usedao {
2.注入bean
   @Resource(name = "user")   ==@Autowired
    user use;
3.    //@Value("张三")
@Value("${name}")-->配置了properties文件
 private String name;

当一个类在spring配置文件中配置了其id,那么它就交给了spring管理,如果下次使用时重新new,那么其通过spring来注入的属性将为空

自动装配

==autowire= byName ==
自动根据属性名注入

 <bean id="student" class="com.ius.demo.Student" lazy-init="true" autowire="byName" >
  </bean >

Aop

面向切面编程

Spring注意到AspectJ在AOP的实现方式上依赖于特殊编译器(ajc编译器),因此Spring很机智回避了这点,转向采用动态代理技术的实现原理来构建Spring AOP的内部机制(动态织入),这是与AspectJ最根本的区别。在AspectJ 1.5后,引入@Aspect形式的注解风格的开发,Spring也非常快地跟进了这种方式,因此Spring 2.0后便使用了与AspectJ一样的注解。

请注意,Spring 只是使用了与 AspectJ 5 一样的注解,但仍然没有使用 AspectJ 的编译器,底层依是动态代理技术的实现,真正的AspectJ参考
https://zhuanlan.zhihu.com/p/25522841
在这里插入图片描述
提供了一个专门的编译器(ajc),在编译时提供横向代码的静态织入

术语

1 织入
将切面代码插入到目标对象,从而生成代理对象的过程
2 切面(Aspect)
封装横切关注点信息的类,每个关注点体现为一个通知方法。
3 通知(Advice)
切面中的方法
4 目标(Target)
被通知的对象
5 代理(Proxy)
向目标对象应用通知之后创建的代理对象
6 连接点(Joinpoint)
方法的调用
7 切入点(pointcut):
类名或方法名

SpringAop(动态代理)

纯java代码实现,不需要专门的编译过程和类加载器

JDK动态代理

Java.lang.reflect.Proxy类实现
条件:目标必须实现接口
实现过程:
1.编写代理类实现接口
2.重写invoke()
原理:在代理类中利用反射生成一个代理类对象

CGLIB代理

不用实现接口,拿类来制造子类
实现过程:
1.编写代理类实现接口
2.重写intercept()

在切面编程时时spring默认为JDK动态代理
这导致生成的代理对象只能转化为接口类型,若想转化为实现类则需要
改为CGLIB代理
<aop:aspectj-autoproxy proxy-target-class=“true”/>

基于代理类的AOP

Spring 通知类型

Around 环绕通知 org.aopalliance.intercept.MethodInterceptor 拦截对目标方法调用
Before 前置通知 org.springframework.aop.MethodBeforeAdvice 在目标方法调用前调用
After 后置通知 org.springframework.aop.AfterReturningAdvice 在目标方法调用后调用
Throws 异常通知 org.springframework.aop.ThrowsAdvice 当目标方法抛出异常时调用
引介通知 在目标类中添加一些新的方法和属性

引介通知的使用

1.在切面类中配置,这里是基于AspectJ的注解式切面类
2.UserDao为目标,Animal为通知接口,AnimalImp为通知接口实现类
其实就是为UserDao添加Animal中的方法

    //引介通知
    @DeclareParents(value = "com.wz.aspectj.target.UserDao+", defaultImpl =AnimalImp.class)
   public Animal animal;

使用
得到的对象需要强转

 UserDao userDao = (UserDao) applicationContext.getBean("userDao");
        // 2 执行方法
//        userDao.addUser();
        userDao.delect();
        Animal animal=(Animal) userDao;

————————————————
ProxyFactoryBean

条件:导入aoplliance-1.0.jar
实现过程:
1.编写切面类
2.配置xml

AspectJ开发

xml

条件:
步骤:
1.xml中定义切面bean
2.配置切面(切入点,通知类型)
3.编写切面类

 <bean id="myAspect" class="com.xml.MyAspect"/>
    <aop:config>
        <aop:aspect id="aspect" ref="myAspect">
            <aop:pointcut expression="execution(* com.xml.UserDaoImpl.*(..))" id="myPointCut"/>
            <aop:before method="myBefore" pointcut-ref="myPointCut"/>
            <aop:after-returning method="myAfterReturning" pointcut-ref="myPointCut" returning="returnVal"/>
            <aop:around method="myAround" pointcut-ref="myPointCut"/>
            <aop:after-throwing method="myAfterThrowing" pointcut-ref="myPointCut" throwing="e"/>
            <aop:after method="myAfter" pointcut-ref="myPointCut"/>
        </aop:aspect>
    </aop:config>
public class MyAspect {
    // 前置通知
    public void myBefore(JoinPoint joinPoint) {
        System.out.print("前置通知 :模拟执行权限检查...,");
        System.out.print("目标类是:"+joinPoint.getTarget() );
        System.out.println(",被织入增强处理的目标方法为:"
                +joinPoint.getSignature().getName());
    }
    // 后置通知
    public void myAfterReturning(JoinPoint joinPoint) {
        System.out.print("后置通知:模拟记录日志...," );
        System.out.println("被织入增强处理的目标方法为:"
                + joinPoint.getSignature().getName());
    }
    // 环绕通知
    public Object myAround(ProceedingJoinPoint proceedingJoinPoint)
            throws Throwable {
        // 开始
        System.out.println("环绕开始:执行目标方法之前,模拟开启事务...");
        // 执行当前目标方法
        Object obj = proceedingJoinPoint.proceed();
        // 结束
        System.out.println("环绕结束:执行目标方法之后,模拟关闭事务...");
        return obj;
    }
    // 异常通知
    public void myAfterThrowing(JoinPoint joinPoint, Throwable e) {
        System.out.println("异常通知:" + "出错了" + e.getMessage());
    }
    // 最终通知
    public void myAfter() {
        System.out.println("最终通知:模拟方法结束后的释放资源...");
    }
}

注解

优点:不用配置aop:config
步骤:
1.编写切面类。额外加上切入点,并加上注解
2.xml中配置包扫描和基于注解的声明式AspectJ支持

    <!-- 指定需要扫描的包,使注解生效 -->
    <context:component-scan base-package="com.wz" />
    <!-- 启动基于注解的声明式AspectJ支持 -->
    <aop:aspectj-autoproxy />
@Aspect
@Component
public class MyAspect {
    // 定义切入点表达式
    @Pointcut("execution(* com.wz.aspectj.target.UserDao.delect(..))")
    //定义切入点名称:通过定义方法来表示切入点名称 (一个返回值为void、方法体为空的方法)
    //切入点名称将作为参数传递给需要执行增强的通知方法
    private void myPointCut(){}
    // 前置通知
    @Before("myPointCut()")
    public void myBefore(JoinPoint joinPoint) {
        System.out.print("前置通知 :模拟执行权限检查...,");
        System.out.print("目标类是:"+joinPoint.getTarget() );
        System.out.println(",被织入增强处理的目标方法为:"
                +joinPoint.getSignature().getName());
    }
    // 后置通知
    @AfterReturning(value="myPointCut()")
    public void myAfterReturning(JoinPoint joinPoint) {
        System.out.print("后置通知:模拟记录日志...," );
        System.out.println("被织入增强处理的目标方法为:"
                + joinPoint.getSignature().getName());
    }
    // 环绕通知
    @Around("myPointCut()")
    public Object myAround(ProceedingJoinPoint proceedingJoinPoint)
            throws Throwable {
        // 开始
        System.out.println("环绕开始:执行目标方法之前,模拟开启事务...");
        // 执行当前目标方法
        Object obj = proceedingJoinPoint.proceed();
        // 结束
        System.out.println("环绕结束:执行目标方法之后,模拟关闭事务...");
        return obj;
    }
    // 异常通知
    @AfterThrowing(value="myPointCut()",throwing="e")
    public void myAfterThrowing(JoinPoint joinPoint, Throwable e) {
        System.out.println("异常通知:" + "出错了" + e.getMessage());
    }
    // 最终通知
    @After("myPointCut()")
    public void myAfter() {
        System.out.println("最终通知:模拟方法结束后的释放资源...");
    }
}

注解(第二次学习学到)

第二步xml可以省略,使用Springconfig配置类
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值