spring概念总结

spring框架

  1. 介绍
    Spring 是 Java EE 编程领域的一款轻量级的开源框架,由被称为“Spring 之父”的 Rod Johnson 于 2002 年提出并创立,它的目标就是要简化 Java 企业级应用程序的开发难度和周期。

  2. 优势
    2.1 轻量级的框架
    2.2 低侵入式 、低污染
    2.3 很好的整合其它框架;可以让任何模块独立起来
    2.4 提供Web层的解决方案
    2.5 提供了强大的、易用的事务管理机制
    2.6 提供了强大的单元测试功能

  3. 核心功能
    1.Ioc和DI
    Ioc:控制反转,将对象的管理交给了spring容器,
    1.对象的声明周期 创建、使用、销毁等等
    2.对象之间的依赖(DI 依赖注入)
    2.AOP:面向切面编程

IoC

spring的xml文件配置

<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
    https://www.springframework.org/schema/beans/spring-beans.xsd">

<beans>标签中可以配置适用于全局的属性
例如:标签中配置default-lazy-init属性是设置该容器下所有的bean是否延时加载

spring容器

注册bean 注册对象
默认情况下,在容器加载期间就会创建所有的对象,并且每个对象都是单例

<bean>标签中的属性值

  • id:bean的唯一标识,通过id获取注册的对象

  • class:类型,根据指定的类型通过反射机制创建对象,默认情况下是通过无参构造方法创建

  • lazy-init:是否延时加载该对象 (default/false:不使用延时加载,在创建容器时,就会创建该对象
    true:在加载容器时不创建该对象,调用getBean方法时,才会创建该对象)

  • scope:设置对象的作用范围(singleton(默认):单例
    prototype:原型 每次通过getBean获取对象时,都会新创建一个该对象
    web相关 : request:该对象的作用域为request域
    session:该对象的作用域为session域 )

  • init-method:指定该对象的初始化方法,在对象创建完成之后,调用该方法

  • destroy-method:指定该对象的销毁方法

当没有为bean指定名称(id/name),名称为 全限定类名#index
name的作用和id一样,name可以为该bean起多个名称 空格隔开即可

DI(依赖注入)

  1. 属性注入(setter注入)
  2. 构造器注入
  3. 自动装配
  4. 工厂注入

属性注入
<bean id="student" class="com.lanou.Student">
name:属性名 例如name=“id” 通过setId方法为该属性赋值
value:为该属性赋的值

<--注入list集合-->
 <property name="li" >
 <list>
  <value>10</value>
   <value>20</value>
  <value>30</value> 
  </list>
 </property>

<-- 注入数组 -->
<property name="arr">
	<array>
	  <value>4</value>
	  <value>5</value>
	</array>
</property>

<!-- 注入map -->
<property name="map">
  <map>
	<entry key="id">
	  <value>10</value>
	</entry>
	<entry key="name">
	  <value>李四</value>
	</entry>
  </map>
</property>

引入其它对象

 <--容器中没有StudentDao对象 -->
  <property name="StudentDao">
      <bean class="com.lanou.StudentDao"></bean>
  </property>

<!-- 容器中有StudentDao对象 -->
<!-- 
	ref:引用spring容器中已经注册的对象,要引用对象的id值
 -->
<!-- <property name="studentDao" ref="studentDao"></property> -->

构造器注入

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v895r3PZ-1656934756153)(1.png)]

 <!-- 构造器注入 -->
 <bean id="student2" class="com.lanou.Student">
<!-- 自上而下为构造方法的第一个参数,第二个参数,....赋值.. -->
<!-- <constructor-arg value="10"></constructor-arg>
<constructor-arg value="张三"></constructor-arg> -->
<!-- index:参数的位置,从0开始 -->
<!-- <constructor-arg index="1" value="名字"></constructor-arg>
<constructor-arg index="0" value="1"></constructor-arg> -->
<!-- name:形参名 -->
<constructor-arg name="id" value="1"></constructor-arg>
<constructor-arg name="name" value="aa"></constructor-arg>
<constructor-arg name="li">
	<list>
		<value>10</value>
		<value>20</value>
	</list>
</constructor-arg>

自动装配

  • byName:如果容器中某个bean的id和对象中某个set方法匹配,
    将该bean通过setter注入到该对象;如果找不到同名的,抛出异常

  • byType:如果容器中某个bean的类型和对象中某个set方法的参数类型匹配,
    将该bean通过setter注入到该对象;如果找不到该类型的bean,就不注入
    如果找到多个同类型的bean,抛出异常

  • constructor:通过构造方法进行注入,
    1.先按照构造方法的参数类型,从容器中找同类型的bean
    如果没找到不注入。如果找到一个,将该bean注入进去。(类似于byType)

    2.如果找到多个同类型的,在同类型的这些bean中,如果某个bean的
    id和构造方法的参数名一致,将同名的注入进去。(byName)

    3.如果没找到同名的,就不注入了


工厂模式

帮助我们创建对象,隐藏了对象的创建以及初始化细节,使用者只需要知道对象的名称即可,需要使用某个对象时,根据名称从工厂获取该对象即可

简单工厂

  1. 实例工厂
  2. 抽象工厂

实例工厂注入

<!-- 1.将工厂注册到spring -->
<bean id="animalFactory" class="com.lanou.factory.AnimalFactory"></bean>
<!-- 
  factory-bean:工厂对象的id
  factory-method:工厂中负责创建对象的方法	
 -->
<bean id="dog" factory-bean="animalFactory" factory-method="getAnimal1">
	<!-- 为factory-method方法传参 -->
	<constructor-arg value="dog"></constructor-arg>
</bean>

** 静态工厂注入 **

  <!-- 
	class:工厂的类名
	factory-method:创建对象的静态方法
 -->
<bean id="cat" class="com.lanou.factory.AnimalFactory" factory-method="getAnimal">
	<constructor-arg value="cat"></constructor-arg>
</bean>

注解

@Configuration:配置类,本质上这个类和配置文件是一个级别的

@ComponentScan(basePackages = {“com.lanou”},basePackageClasses = SpringConfig.class)相当于>配置文件的context:component-scan标签
多个同类型的bean,我们通过byType获取时,优先获取@Primary修饰的
@Primary

从容器中找到MyService对象,赋值给了方法的参数
public StudentController studentController(@Autowired MyService myService) {
	System.out.println(myService);
	StudentController sc = new StudentController();
	sc.setMyService(myService);
	return sc;
}

注解(配置)类加载
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);

  • @Component(“mc”):将当前类的对象注册到spring容器中,id默认为首字母小写的类名
    value属性可以为对象指定id的值

  • @Lazy(value = false):是否延时加载 等同于bean的lazy-init属性

  • @Scope(scopeName = “singleton”):等同于bean标签的scope属性

向Controller层注入service层

@Autowired
默认为byType
required:默认值为true
true:当前对象必须依赖注入的对象,如果找不到合适的bean注入,就抛出异常
false:如果找不到合适的bean,就不注入了

@Qualifier(“myServiceImpl”):配合@Autowired 以byName的方式查找合适的bean注入

@Resource(name = “myServiceImpl”):java自带的注入注解

@PostConstruct相当于init-met

@PreDestroy相当于destory-method

spring文件中的配置

扫描指定的包,根据每个类的注解,将对应的对象注册进spring容器
base-package:要扫描的包;会扫描此包,以及此包的子孙包
被扫描的类上面有@Component、@Controller、@Service、@Repository、@RestController等注解
就会被注册到spring容器中
字段上面有@Autowired,从容器中找合适的bean进行依赖注入

<context:component-scan base-package="com.lanou"></context:component-scan>

代理模式

为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

  • 目标对象(target Class):实现了核心功能的对象

  • 代理对象(proxy Class):在代理类中包含了目标对象,可以对目标对象的访问做控制。在目标对象的功能开始之前或者结束之后等时机添加额外功能。

  • 抽象类:制定规范,可以使接口或者抽象类;一般情况下,目标类和与之对应的代理类实现同一个接口或者继承同一个抽象类,使用者不论使用代理还是目标对象 所做的操作是一样的。

代理模式的实现;

  1. 静态代理:在编译期间,就需要定义好代理类
  2. 动态代理:在运行时,根据需要生成代理类 例如mybatis中的getMapper方法

JDK动态代理(接口代理):根据接口,生成接口的实现类作为代理类。目标类必须有接口
CGLIB动态代理:根据目标类生成目标类的子类(派生类)作为代理类。目标类有没有接口都行
CGLIB效率高于JDK动态代理
类似于拦截器的类,当动态生成代理对象调用方法时,会去执行拦截器中的方法,在拦截器的方法中,我们处理功能。实现还是通过反射机制

静态代理:自行创建功能类,并将功能类的方法装饰在目标类的目标方法上

动态代理

  1. JDK动态代理
    实现InvocationHandler接口 并实现invoke方法
    通过JDK动态代理生成的代理对象,调用方法时,就会执行invoke方法

    • 参数:
    • 1.代理对象
    • 2.目标对象中对应的方法
    • 3.2中方法需要的参数
      返回值就是method方法执行完之后的返回值

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    System.out.println(“invoke”);
    tx.begin();
    try {
    //执行目标对象中的方法
    return method.invoke(this.target, args);
    } catch (Exception e) {
    tx.rollback();
    }finally {
    tx.commit();
    }

     return null;
    

    }

    public static void main(String[] args) {
    //目标类
    StudentDao target = new StudentDaoTatget();
    //需要装饰目标类方法的工具类
    TransactionAspect tx = new TransactionAspect();
    MyHandler mh = new MyHandler(target, tx);

     //动态生成代理对象
     /*
      * 1.loader:类加载器
      * 2.interfaces:目标类所实现的接口
      * 3.h:invocationHandler对象,通过生成代理对象调用方法时,就回去回调指定
      * 	      的handler对象中的invoke方法。
      */
     StudentDao proxy = (StudentDao)Proxy.newProxyInstance(target.getClass().getClassLoader(),
     					   target.getClass().getInterfaces(), 
     					   mh);
    

    S ystem.out.println(proxy.getClass());
    proxy.update(1);
    }

2.CGLIB动态代理

public static void main(String[] args) {
	
MethodInterceptor mi =	new MethodInterceptor() {
		private StudentDao target = new StudentDaoTatget();
		private TransactionAspect tx = new TransactionAspect();
		/*
		 * MethodProxy:为需要执行的方法生成的代理对象,
		 * 				据说,使用该方法代理执行目标对象中的方法效率高
		 */
		@Override
		public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
			System.out.println("intercept");
			tx.begin();
			try {
				//return method.invoke(this.target, args);
				return methodProxy.invokeSuper(proxy, args);
			} catch (Exception e) {
				tx.rollback();
			}finally {
				tx.commit();
			}
			
			return null;
		}
	};
	
	//通过CGLIB生成代理对象
	Enhancer enhancer = new Enhancer();
	//将目标类设置为父类
	enhancer.setSuperclass(StudentDaoTatget.class);
	//设置方法拦截器,通过代理对象调用方法时,就会执行拦截器中的intercept方法
	enhancer.setCallback(mi);
	//生成代理对象
	StudentDaoTatget proxy = (StudentDaoTatget)enhancer.create();
	System.out.println(proxy.getClass());
	proxy.delete();
	
}

对应的类文件如下
在这里插入图片描述

AOP概念:

  1. 目标对象:拥有核心功能的对象
  2. 代理对象:是目标对象的一个代理方,在代理对象中,在合适的时机为目标对象中的方法添加额外方法。例如方法执行之前,之后等等。
  3. 连接点:目标对象中可执行的方法,这些方法都可以被添加额外功能。
  4. 切入点:本质上就是一个表达式,符合该表达式的连接点需要被添加额外功能
  5. 切面:就是一个类,这个类中定义着额外功能。
  6. 通知:切面类中的那些方法,都可以是通知。
    1.前置通知
    2.后置通知
    3.异常通知
    4.最终通知
    5.环绕通知
  7. 织入:根据目标对象和切面类动态生成代理对象的过程。

AOP:面向切面的编程,某些非业务核心功能,但是整个系统中多个对象中都需要使用,此时,我们可以通过AOP来动态的为核心对象添加这些额外的功能,降低了非核心功能和核心功能的耦合度。后期正价好维护。例如 事务、日志等功能。

AOP配置文件

 <?xml version="1.0" encoding="UTF-8"?>
 <beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:context="http://www.springframework.org/schema/context"
   xmlns:aop="http://www.springframework.org/schema/aop"
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
http://www.springframework.org/schema/aop 
http://www.springframework.org/schema/aop/spring-aop.xsd">

<!-- 目标对象 -->
<bean id="target" class="com.lanou.dao.StudentDaoTatget"></bean>
<!-- 切面对象 -->
<bean id="myAspect" class="com.lanou.aspect.MyAspect"></bean>

<!-- aop相关配置 
	proxy-target-class:默认值为false,是用来指定用哪种方式生成代理对象
	false:如果目标类有接口,就使用JDK动态代理;如果没有接口,就使用CGLIB
	true:只使用CGLIB动态代理
-->
<aop:config proxy-target-class="false">
	<!-- 切入点配置 -->
	<aop:pointcut expression="execution(* com.lanou.dao..*.*(..))" id="pc"/>
	<!-- 切面 -->
	<aop:aspect ref="myAspect">
		<aop:before method="before" pointcut-ref="pc"/>
		<aop:after-returning method="afterReturning" pointcut-ref="pc"/>
		<aop:after-throwing method="afterThrowding" pointcut-ref="pc"/>
		<aop:after method="after" pointcut-ref="pc"/>
		<aop:around method="around" pointcut-ref="pc"/>
	</aop:aspect>
</aop:config>
</beans>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值