Spring5学习笔记总结

一.Spring概述

Spring 是轻量级的开源的 JavaEE 框架,Spring为简化企业级开发而生,使用Spring开发可以将Bean对象,Dao组件对象,Service组件对象等交给Spring容器来管理,这样使得很多复杂的代码在Spring中开发却变得非常的优雅和简洁,有效的降低代码的耦合度,极大的方便项目的后期维护、升级和扩展。

Spring 有两个核心部分:IOC 和 Aop

(1)IOC:控制反转,指的是将对象的创建权交给Spring去创建,使用Spring之前,对象的创建都是由我们自己在代码中new创建。而使用Spring之后。对象的创建都是由给了Spring框架。

(2)Aop:面向切面,不修改源代码进行功能增强。

Spring快速入门

  1. 导入Spring 坐标

    <dependencies>
         <dependency>
           <groupId>org.springframework</groupId>`
           <artifactId>spring-context</artifactId>
           <version>${spring.version}</version>`
        </dependency>
    </dependencies>
    
  2. 创建Bean

    public interface UserDao {
        public void save();
    }
    
    public class UserDaoImpl implements UserDao {
        @Override
        public void save() {
            System.out.println("UserDao Startinng....");
        }
    }
    
  3. 创建Spring核心配置文件 applicationContext.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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans 				   	http://www.springframework.org/schema/beans/spring-beans.xsd">
        <bean id="userDao" class="com.terence.dao.impl.UserDaoImpl"></bean>
    </beans>
    
  4. 创建ApplicationContext对象,通过getBean方法获得Bean实例

    public class UserDaoDemo {
        public static void main(String[] args) {
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
            UserDao userDao = (UserDao) applicationContext.getBean("userDao");
            userDao.save();
        }
    }
    

二. IOC

1. IOC操作Bean管理

1、基于 xml方式创建对象

(1)在 spring 配置文件中,使用 bean 标签,标签里面添加对应属性,就可以实现对象创建

(2)在 bean 标签有很多属性,介绍常用的属性

​ id 属性:唯一标识

​ class 属性:类全路径(包类路径)

(3)创建对象时候,默认也是执行无参数构造方法完成对象创建

2、基于 xml方式注入属性

​ DI:依赖注入,就是注入属性

3、第一种注入方式:使用 set 方法进行注入

(1)创建类,定义属性和对应的 set 方法

public class User {
 //创建属性
 private String Name;
 private String Age;
 //创建属性对应的 set 方法
 public void setName(String Name) {
 this.Name = Name;
 }
 public void setAge(String Age) {
 this.Age = Age;
 } 
}

(2)在 spring 配置文件配置对象创建,配置属性注入

<bean id="User" class="com.yaoqi.bean.User">
 <!--使用 property 完成属性注入
     name:类里面属性名称
     value:向属性注入的值
 -->
 <property name="Name" value="张三"></property>
 <property name="Age" value="1"></property>
</bean> 
4、第二种注入方式:使用有参数构造进行注入

(1)创建类,定义属性,创建属性对应有参数构造方法

/使用有参数构造注入/使用有参数构造注入/
public class User {
 //属性
 private String name;
 private String age;
 //有参数构造
 public User(String name,String age) {
 this.name = name;
 this.age = age;
 } 
}

(2)在 spring 配置文件中进行配置

<!--3 有参数构造注入属性--> 
<bean id="User" class="com.yaoqi.bean.User">
 <constructor-arg name="name" value="张三"></constructor-arg>
 <constructor-arg name="age" value="18"></constructor-arg>
</bean> 

2. 注入其他类型属性

1、字面量

(1)null 值

<property name="属性名">
 	<null/>
</property> 

(2)属性值包含特殊符号

  • 把<>进行转义 < >

  • 把带特殊符号内容写到 CDATA

<property name="属性名">
    <!--设置值为<<深圳>>-->
 <value><![CDATA[<<深圳>>]]></value>
</property> 

2、注入属性-外部 bean

(1)创建两个类 service 类和 dao 类

(2)在 service 调用 dao 里面的方法

(3)在 spring 配置文件中进行配置

public class UserService {
 //创建 UserDao 类型属性,生成 set 方法
 private UserDao userDao;
 public void setUserDao(UserDao userDao) {
	 this.userDao = userDao;
 }
    
 public void add() {
     System.out.println("service add...............");
     userDao.update();
 } 
}
<bean id="userService" class="com.yaoqi.service.UserService">
 	<property name="userDao" ref="userDaoImpl"></property>
</bean> 
<bean id="userDaoImpl" class="com.yaoqi.dao.UserDaoImpl"></bean> 

3、注入属性-内部 bean

(1)一对多关系:部门和员工

(2)在实体类之间表示一对多关系,员工表示所属部门,使用对象类型属性进行表示

//部门类
public class Dept {
 private String dname;
 public void setDname(String dname) {
	 this.dname = dname;
 } 
}

//员工类
public class Emp {
     private String ename;
     private String gender;
     private Dept dept;
    
     public void setDept(Dept dept) {
     	this.dept = dept;
     }
     public void setEname(String ename) {
    	 this.ename = ename;
     }
     public void setGender(String gender) {
    	 this.gender = gender; 
     } 
}

(3)在 spring 配置文件中进行配置

<bean id="emp" class="com.yaoqi.bean.Emp">
 <!--设置两个普通属性-->
 <property name="ename" value="张三"></property>
 <property name="gender" value=""></property>
 <!--设置对象类型属性-->
 <property name="dept">
 	<bean id="dept" class="com.yaoqi.bean.Dept">
     	<property name="dname" value="销售部"></property>
    </bean>
 </property>
</bean> 

4、注入属性-级联赋值

(1)第一种写法

<bean id="emp" class="com.yaoqi.bean.Emp">
 <!--设置两个普通属性-->
 <property name="ename" value="张三"></property>
 <property name="gender" value=""></property>
 <!--级联赋值-->
 <property name="dept" ref="dept"></property>
</bean> 

<bean id="dept" class="com.yaoqi.bean.Dept">
 <property name="dname" value="销售部"></property>
</bean> 

(2)第二种写法

<bean id="emp" class="com.yaoqi.bean.Emp">
 <!--设置两个普通属性-->
 <property name="ename" value="张三"></property> 
 <property name="gender" value=""></property>
 <!--级联赋值-->
 <property name="dept.dname" value="销售部"></property>
</bean> 

3. 注入集合属性

1、注入数组类型属性

2、注入 List 集合类型属性

3、注入 Map 集合类型属性

(1)创建类,定义数组、list、map、set 类型属性,生成对应 set 方法

public class Stu {
 //1 数组类型属性
 private String[] courses;
 //2 list 集合类型属性
 private List<String> list;
 //3 map 集合类型属性
 private Map<String,String> maps;
 //4 set 集合类型属性
 private Set<String> sets;

 public void setSets(Set<String> sets) {
 	this.sets = sets;
 }

 public void setCourses(String[] courses) {
 	this.courses = courses;
 }

 public void setList(List<String> list) {
 	this.list = list;
 }

 public void setMaps(Map<String, String> maps) {
 	this.maps = maps;
 } 
}

(2)在 spring 配置文件进行配置

<bean id="stu" class="com.yaoqi.bean.Stu">
 <!--数组类型属性注入-->
 <property name="courses">
     <array>
         <value>A</value>
         <value>B</value>
     </array>
 </property>

 <!--list 类型属性注入-->
 <property name="list">
     <list> 
         <value>A</value>
         <value>B</value>
     </list>
 </property>

 <!--map 类型属性注入-->
 <property name="maps">
     <map>
         <entry key="A" value="a"></entry>
         <entry key="B" value="b"></entry>
     </map>
 </property>

 <!--set 类型属性注入-->
 <property name="sets">
     <set>
         <value>A</value>
         <value>B</value>
     </set>
 </property>
</bean> 

4、在集合里面设置对象类型值

<!--创建多个class对象--> 
<bean id="class1" class="com.yaoqi.bean.Class">
 	<property name="cname" value="语文"></property>
</bean> 
<bean id="class2" class="com.yaoqi.bean.Class">
 	<property name="cname" value="数学"></property>
</bean>

<!--注入 list 集合类型,值是对象--> 
<property name="classList">
     <list>
         <ref bean="class1"></ref>
         <ref bean="class2"></ref>
     </list>
</property> 

4. 工厂Bean(FactoryBean)

1、Spring 有两种类型 bean,一种普通 bean,另外一种工厂 bean(FactoryBean)

2、普通 bean:在配置文件中定义 bean 类型就是返回类型

3、工厂 bean:在配置文件定义 bean 类型可以和返回类型不一样

第一步 创建类,让这个类作为工厂 bean,实现接口 FactoryBean

第二步 实现接口里面的方法,在实现的方法中定义返回的 bean 类型

public class MyBean implements FactoryBean<Class> {
 //定义返回 bean
 @Override
 public Course getObject() throws Exception {
     Course course = new Course();
     course.setCname("英语");
     return course;
 }

 @Override
 public Class<?> getObjectType() {
	 return null;
 }

 @Override
 public boolean isSingleton() {
	 return false;
 } 
}
<bean id="myBean" class="com.yaoqi.factorybean.MyBean">
</bean>
@Test
public void test3() {
     ApplicationContext context = new ClassPathXmlApplicationContext("bean3.xml");
     Course course = context.getBean("myBean", Course.class);
     System.out.println(course);
}

5. Bean作用域

scope:指对象的作用范围,取值如下:

取值范围说明
singleton默认值,单例的
prototype多例的
requestWEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 request 域中
sessionWEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 session 域中
global sessionWEB 项目中,应用在 Portlet 环境,如果没有 Portlet 环境那么globalSession 相当于 session

6. Bean 生命周期

  1. 执行无参数构造创建Bean实例

  2. 调用set方法设置属性值

    —初始之前执行的方法

  3. 执行初始化的方法

    —初始之后执行的方法

  4. 获取创建Bean实例对象

  5. 执行销毁的方法

(1)创建类,实现接口 BeanPostProcessor,创建后置处理器

public class MyBeanPost implements BeanPostProcessor {
 @Override
 public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
     System.out.println("这是在初始化之前执行的方法");
     return bean;
 }

 @Override
 public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
     System.out.println("这是在初始化之后执行的方法");
     return bean;
 } 
}
<!--配置后置处理器--> 
<bean id="myBeanPost" class="com.yaoqi.bean.MyBeanPost"></bean>

7. 外部属性文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-60WWDvFb-1658717351881)(C:\Users\KONGP\Desktop\总笔记\01-Spring\image-20220628173255831.png)]

把外部 properties 属性文件引入到 spring 配置文件中引入 context 名称空间

<beans xmlns="http://www.springframework.org/schema/beans"  
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
       xmlns:p="http://www.springframework.org/schema/p" 
       xmlns:util="http://www.springframework.org/schema/util" 
       	xmlns:context="http://www.springframework.org/schema/context" 
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans.xsd 
http://www.springframework.org/schema/util 
http://www.springframework.org/schema/util/spring-util.xsd
<!--context空间名称-->                          
http://www.springframework.org/schema/context 
http://www.springframework.org/schema/context/spring-context.xsd"> 

在 spring 配置文件使用标签引入外部属性文件

<context:property-placeholder location="classpath:jdbc.properties"/>
<!--配置连接池--> 
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
     <property name="driverClassName" value="${prop.driverClass}"></property>
     <property name="url" value="${prop.url}"></property>
     <property name="username" value="${prop.userName}"></property>
     <property name="password" value="${prop.password}"></property>
</bean>

三.Spring常用注解

@Component 使用在类上用于实例化Bean
@Controller 使用在web层类上用于实例化Bean
@Service 使用在service层类上用于实例化Bean
@Repository 使用在dao层类上用于实例化Bean
@Autowired 使用在字段上用于根据类型依赖注入
@Qualifier 结合@Autowired一起使用用于根据名称进行依赖注入
@Resource 相当于@Autowired+@Qualifier,按照名称进行注入
@Value 注入普通属性
@Scope 标注Bean的作用范围

@Configuration 用于指定当前类是一个 Spring 配置类,当创建容器时会从该类上加载注解
@Bean 使用在方法上,标注将该方法的返回值存储到 Spring 容器中
@PropertySource 用于加载.properties 文件中的配置
@Import 用于导入其他配置类

使用注解进行开发时,需要在applicationContext.xml中配置组件扫描,作用是指定哪个包及其子包下的Bean需要进行扫描以便识别使用注解配置的类、字段和方法,或者使用@ComponentScan注解,用于指定 Spring 在初始化容器时要扫描的包。

<!--注解的组件扫描-->
<context:component-scan base-package="com.yaoqi"></context:component-scan>

四.AOP

1. AOP 的作用及其优势

作用:在程序运行期间,在不修改源码的情况下对方法进行功能增强

优势:减少重复代码,提高开发效率,并且便于维护

2. AOP 的底层实现

实际上,AOP 的底层是通过 Spring 提供的的动态代理技术实现的。在运行期间,Spring通过动态代理技术动态的生成代理对象,代理对象方法执行时进行增强功能的介入,在去调用目标对象的方法,从而完成功能的增强。

3. AOP 的动态代理技术

第一种 有接口情况,使用 JDK 动态代理(创建接口实现类代理对象,增强类的方法)

第二种 没有接口情况,使用 CGLIB 动态代理(创建子类的代理对象,增强类的方法)

(1)创建接口,定义方法

public interface UserDao {
 public int add(int a,int b);
}

(2)创建接口实现类,实现方法

public class UserDaoImpl implements UserDao {
 @Override
 public int add(int a, int b) {
	 return a+b;
 }
}

(3)使用 Proxy 类创建接口代理对象

public class JDKProxy {
 public static void main(String[] args) {
 //创建接口实现类代理对象
     Class[] interfaces = {UserDao.class};
     UserDaoImpl userDao = new UserDaoImpl();
     UserDao dao = (UserDao)Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao)); 
     int result = dao.add(1, 2);
     System.out.println("result:"+result);
 } 
}

//创建代理对象代码
class UserDaoProxy implements InvocationHandler {
     //1 把创建的是谁的代理对象,把谁传递过来
     //有参数构造传递
     private Object obj;
     public UserDaoProxy(Object obj) {
     this.obj = obj;
 }

 //增强的逻辑
 @Override
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
     System.out.println("方法之前执行....");
     //被增强的方法执行
     Object result = method.invoke(obj, args);
     System.out.println("方法之后执行....");
     return result;
 } 
}

4. AOP 的相关术语

常用的术语如下:
Target(目标对象):代理的目标对象
Proxy (代理):一个类被 AOP 织入增强后,就产生一个结果代理类
Joinpoint(连接点):所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点
Pointcut(切入点):所谓切入点是指我们要对哪些 Joinpoint 进行拦截的定义
Advice(通知/ 增强):所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知
Aspect(切面):是切入点和通知(引介)的结合
Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程。spring采用动态代理织入,而AspectJ采用编译期织入和类装载期织入

5. AOP 操作(AspectJ 注解)

1、创建类,在类里面定义方法

public class User {
 public void add() {
	 System.out.println("add starting...");
 } 
}

2、创建增强类(编写增强逻辑)

(1)在增强类里面,创建方法,让不同方法代表不同通知类型

//增强的类
public class UserProxy {
 public void before() {
 	System.out.println("before starting...");
 } 
}

3、进行通知的配置

(1)在 spring 配置文件中,开启注解扫描

<?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" 
 xmlns:aop="http://www.springframework.org/schema/aop" 
 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">

 <!-- 开启注解扫描 -->
 <context:component-scan base-package="com.yaoqi.package"></context:component-scan> 

(2)使用注解创建 User 和 UserProxy 对象

(3)在增强类上面添加注解 @Aspect

//增强的类
@Component
@Aspect //生成代理对象
public class UserProxy {

(4)在 spring 配置文件中开启生成代理对象

<aop:aspectj-autoproxy></aop:aspectj-autoproxy> 

4、配置不同类型的通知

(1)在增强类的里面,在作为通知方法上面添加通知类型注解,使用切入点表达式配置

@Component
@Aspect 
public class UserProxy {
 //前置通知
 @Before(value = "execution(*com.yaoqi.package.User.add(..))")
 public void before() {
	 System.out.println("before.........");
 }

 //后置通知
 @AfterReturning(value = "execution(*com.yaoqi.package.User.add(..))")
 public void afterReturning() {
	 System.out.println("afterReturning.........");
 }

 //最终通知
 @After(value = "execution(*com.yaoqi.package.User.add(..))")
 public void after() {
 	System.out.println("after.........");
 }

 //异常通知
 @AfterThrowing(value = "execution(*com.yaoqi.package.User.add(..))")
 public void afterThrowing() {
 	System.out.println("afterThrowing.........");
 }

 //环绕通知
 @Around(value = "execution(*com.yaoqi.package.User.add(..))")
 public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
     System.out.println("环绕之前.........");
     //被增强的方法执行
     proceedingJoinPoint.proceed();
     System.out.println("环绕之后.........");
 } 
}

5、相同的切入点抽取

//相同切入点抽取
@Pointcut(value = "execution(*com.yaoqi.package.User.add(..))")
public void commondemo() {
}

//前置通知
@Before(value = "commondemo()")
public void before() {
 System.out.println("before.........");
}

6. AOP 操作(AspectJ 配置文件)

1、创建两个类,增强类和被增强类,创建方法

2、在 spring 配置文件中创建两个类对象

<bean id="book" class="com.yaoqi.Book"></bean> 
<bean id="bookProxy" class="com.yaoqi.BookProxy"></bean> 

3、在 spring 配置文件中配置切入点

<!--配置 aop 增强--> 
<aop:config>
 <!--切入点-->
 <aop:pointcut id="p" expression="execution(*com.yaoqi..Book.buy(..))"/>
 <!--配置切面-->
 <aop:aspect ref="bookProxy">
 <!--增强作用在具体的方法上-->
     <aop:before method="before" pointcut-ref="p"/>
 </aop:aspect>
</aop:config>


5、相同的切入点抽取

//相同切入点抽取
@Pointcut(value = "execution(*com.yaoqi.package.User.add(..))")
public void commondemo() {
}

//前置通知
@Before(value = "commondemo()")
public void before() {
 System.out.println("before.........");
}

7. AOP 操作(AspectJ 配置文件)

1、创建两个类,增强类和被增强类,创建方法

2、在 spring 配置文件中创建两个类对象

<bean id="book" class="com.yaoqi.Book"></bean> 
<bean id="bookProxy" class="com.yaoqi.BookProxy"></bean> 

3、在 spring 配置文件中配置切入点

<!--配置 aop 增强--> 
<aop:config>
 <!--切入点-->
 <aop:pointcut id="p" expression="execution(*com.yaoqi..Book.buy(..))"/>
 <!--配置切面-->
 <aop:aspect ref="bookProxy">
 <!--增强作用在具体的方法上-->
     <aop:before method="before" pointcut-ref="p"/>
 </aop:aspect>
</aop:config>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

幺柒.

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

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

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

打赏作者

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

抵扣说明:

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

余额充值