Spring框架汇总(大学生的天堂 码农的圣殿)
企业级开发框架
- Spring Framework 是整个 Spring 生态的基础,各个模块都是基于 Spring Framework 衍生出来的。
- Spring Boot 是一个快速开发框架,让开发者可以快速搭建一套基于 Spring 的应用程序,集成了 Spring 其他模块以及第三方模块,MyBatis、Hibernate 等,只需简单的配置就可以使用,开箱即用,默认支持 JSON 格式,实现前后端开发非常方便,Spring Boot + Vue。
- Spring Cloud 是一套整合了分布式应用常用模块的框架,基于 Spring Boot。
Maven:软件管理工具
POM:Project Object Model,就是一个 XML 文件,配置 jar 依赖关系。
Spring要解决的问题
- ① 解决依赖注入的问题,让使用者的代码能够完成解耦工作。
- ② 依赖注入DI:
- 一个类的对象,需要正常执行,首先需要把另外一个对象注入进来。
- Spring的核心依然是依赖注入,Spring替我们完成了依赖注入,所以,对于使用者来说,我们在用的功能是叫控制反转(IOC)。
- 控制反转IOC:
- 为什么要IOC:如果存在大量的接口,需要实现类来完成注入工作。那么一旦需要修改实现类的时候,所有的这些被注入的实现类都需要通过修改源码的方式来进行修改。如果修改遗漏,或者检查起来都特别的麻烦。
Spring 应用程序
两个bean的级联
集合的注入
Spring继承
Spring依赖
P命名空间
IOC工厂方法
IOC自动装载
Ioc的开发方式
Aop
Spring 应用程序
1、Idea创建 Maven 工程。
2、pom.xml 中引入 Spring 依赖。
<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.1.7.RELEASE</version></dependency>
</dependencies>
Spring 的两大核心机制:IoC(控制反转) 和 AOP(面向切面编程)
IoC 对象创建不再由开发者完成,而是容器自动创建,开发者直接取出来用即可。
3、创建 applicationContext.xml
此 处 默 认 实 体 类 已 经 创 建 完 成。
<?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" xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p"xmlns:util="http://www.springframework.org/schema/util" xmlns:jdbc="http://www.springframework.org/schema/jdbc"xmlns:cache="http://www.springframework.org/schema/cache"xsi:schemaLocation="http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/jdbchttp://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsdhttp://www.springframework.org/schema/cachehttp://www.springframework.org/schema/cache/spring-cache-3.1.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/utilhttp://www.springframework.org/schema/util/spring-util.xsd"><bean id="stu" class="com.chenny.entity.Student" ><property name="id" value="1"></property><property name="name" value="张三"></property><property name="age" value="22"></property></bean></beans>
XmlBeanFactory和ClassPathXmlApplicationContext的区别
- XmlBeanFactory:
- a. 延迟加载,在调用getBean的时候完成实例的创建
- b. 带来的问题:在运行时会大量消耗资源,没有单例
- ClassPathXmlApplicationContext
- a. 默认是容器加载后,同时创建了所有的bean;默认是单例,即他的作用域是singleton;这个单例并不是真正意义上的单例,只是容器始终只创建这么一个bean的实例
- b. 当作用域为prototype的时候,即bean被延迟加载
- c. 面试很容易会被问到bean的默认情况,以及如何修改
Bean的作用域
- 静态工厂
- a. 静态工厂,不再是Spring来直接调用构造
- b. 必须用懒加载,因为让Spring容器启动的时候,如果不是懒加载,那么他会去调用对应的构造!!!(既是工厂又是单例,推荐使用懒加载。)
- c. 比方说,有些数据需要等到容器正式启动完,数据准备好以后,再获取bean的时候才能正常执行
- d. 容器只创建了一次实例,可以通过设置作用域来指定是单例还是多例
4、加载 IoC 容器,获取创建好的 bean。
public class IoCTest {public static void main(String[] args) {//1.加载 IoC 容器,spring.xmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");Student student = (Student) applicationContext.getBean("stu");System.out.println(student);}
}
特殊字符的处理方式。
<?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="stu" class="com.chenny.entity.Student" ><property name="id" value="1"></property>
<!-- <property name="name" value="<张三>"></property>--><property name="name"><value><![CDATA[<张三>]]></value></property><property name="age" value="22"></property></bean></beans>
使用 IoC 容器创建对象,实体类的注意事项:
- 必须有无参构造函数。
- 成员变量必须有 setter 方法。
IoC 实例化对象的过程,通过反射+XML解析的方式对 spring.xml 进行处理,反射拿到无参构造函数,调用创建对象,同时获取 setter 方法,调用完成成员变量的赋值。
获取 IoC bean 的方式
- 通过 id 获取
Student student = (Student) applicationContext.getBean("stu");
- 通过运行时类获取
Student student = applicationContext.getBean(Student.class);
通过运行时类获取 bean 存在一个弊端,当 spring.xml 中配置两个 Student 的 bean 时会抛出异常。
创建 IoC bean 的方式
- 无参构造
<bean id="stu2" class="com.chenny.entity.Student"><property name="id" value="2"></property><property name="name" value="李四"></property><property name="age" value="23"></property>
</bean>
- 有参构造
1、在实体类中创建有参构造。
public Student(Integer id, String name, Integer age) {this.id = id;this.name = name;this.age = age;
}
2、在 spring.xml 中进行配置。
<bean id="stu3" class="com.chenny.entity.Student"><constructor-arg index="1" value="王五"></constructor-arg><constructor-arg index="0" value="1"></constructor-arg><constructor-arg index="2" value="20"></constructor-arg>
</bean>
<bean id="stu3" class="com.chenny.entity.Student"><constructor-arg name="name" value="王五"></constructor-arg><constructor-arg name="id" value="1"></constructor-arg><constructor-arg name="age" value="20"></constructor-arg>
</bean>
<bean id="stu3" class="com.chenny.entity.Student"><constructor-arg value="1"></constructor-arg><constructor-arg value="王五"></constructor-arg><constructor-arg value="20"></constructor-arg>
</bean>
返回顶层
两个 bean 的级联
package com.chenny.entity;public class Student {private Integer id;private String name;private Integer age;private Classes classes;public Classes getClasses() {return classes;}public void setClasses(Classes classes) {this.classes = classes;}public void setId(Integer id) {this.id = id;}public void setName(String name) {this.name = name;}public void setAge(Integer age) {this.age = age;}@Overridepublic String toString() {return "Student{" +"id=" + id +", name='" + name + '\'' +", age=" + age +", classes=" + classes +'}';}public Student(Integer id, String name, Integer age) {this.id = id;this.name = name;this.age = age;}public Student() {}
}
package com.chenny.entity;public class Classes {private Integer id;private String name;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "Classes{" +"id=" + id +", name='" + name + '\'' +'}';}
}
<bean id="stu2" class="com.chenny.entity.Student"><property name="id" value="2"></property><property name="name" value="李四"></property><property name="age" value="23"></property><property name="classes" ref="classes1"></property>
</bean><bean id="classes1" class="com.chenny.entity.Classes"><property name="id" value="1"></property><property name="name" value="Java班"></property>
</bean>
返回顶层
Spring 继承
- Spring Bean 定义的继承与 Java 类的继承无关,但是继承的概念是一样的。
- ⼦ bean 可以继承⽗ bean 的属性值。
Customer
package com.chenny.entity;public class Customer {private int type;private String action;private String Country;//.....set,get,constructor
customer.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/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd"><!-- abstract如果为true,你就不能实例化它了 --><bean id="BaseCustomerMalaysia" class="com.chenny.entity.Customer" abstract="true"><property name="action" value="sell"></property><property name="country" value="Malaysia" /></bean><bean id="CustomerBean" parent="BaseCustomerMalaysia"><property name="action" value="buy" /><property name="type" value="1" /></bean></beans>
App
package com.chenny.test;import com.chenny.entity.Customer;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class App {public static void main(String[] args) {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("customer.xml");Customer customer = (Customer) applicationContext.getBean("CustomerBean");System.out.println(customer);}
}
返回顶层
Spring 依赖
A 依赖于 B,则⼀定会先创建 B,再创建 A。
test.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 name="user" class="com.chenny.entity.User" depends-on="car"><property name="id" value="1"></property><property name="name" value="张三"></property></bean><bean name="car" class="com.chenny.entity.Car"><property name="id" value="1"></property><property name="brand" value="BWP"></property></bean>
</beans>
User
package com.chenny.entity;public class User {private Integer id;private String name;public User() {System.out.println("User创建了!");}public User(Integer id, String name) {this.id = id;this.name = name;}@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +'}';}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}
Car
package com.chenny.entity;public class Car {private Integer id;private String brand;public Car() {System.out.println("Car创建了!");}public Car(Integer id, String brand) {this.id = id;this.brand = brand;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getBrand() {return brand;}public void setBrand(String brand) {this.brand = brand;}@Overridepublic String toString() {return "Car{" +"id=" + id +", brand='" + brand + '\'' +'}';}
}
DependsOnTest
package com.chenny.test;import com.chenny.entity.Car;
import com.chenny.entity.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class DependsOnTest {public static void main(String[] args) {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("test.xml");User user = (User) applicationContext.getBean("user");Car car = (Car) applicationContext.getBean("car");}
}
返回顶层
P命名空间
p 命名空间实际是通过调⽤成员变量的 setter ⽅法来完成赋值的,如果是 bean 之间的级联映射,需要调⽤ p:属性名-ref 来配置。
<?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:p="http://www.springframework.org/schema/p"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="world" class="com.chenny.World"/><!-- 通过set方法注入的传统的bean定义 --><bean id="hello1" class="com.chenny.Hello"><property name="p1" value="v1"/><property name="p2" value="v2"/><property name="world" ref="world"/></bean><!-- 通过set方法注入的使用p命名空间的bean定义 --><bean id="hello2" class="com.chenny.Hello" p:p1="v1" p:p2="v2" p:world-ref="world"/></beans>
返回顶层
Spring IoC ⼯⼚⽅法
IoC 是典型的⼯⼚模式,如何使⽤⼯⼚模式创建 bean, IoC 通过⼯⼚模式创建 bean 有两种⽅式:
- 静态⼯⼚⽅法
- 实例⼯⼚⽅法
Car
package com.chenny.entity;public class Car {private Integer id;private String brand;public Car() {System.out.println("Car创建了!");}public Car(Integer id, String brand) {this.id = id;this.brand = brand;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getBrand() {return brand;}public void setBrand(String brand) {this.brand = brand;}@Overridepublic String toString() {return "Car{" +"id=" + id +", brand='" + brand + '\'' +'}';}
}
静态⼯⼚⽅法
StaticFactory
package com.chenny.factory;import com.chenny.entity.Car;import java.util.HashMap;
import java.util.Map;public class StaticFactory {public static Map<Integer, Car> cars;static {cars = new HashMap<Integer, Car>();cars.put(1,new Car(1,"奔驰"));cars.put(2,new Car(2,"宝马"));cars.put(3,new Car(3,"幻影"));}public static Map<Integer, Car> getCars() {return cars;}public static void setCars(Map<Integer, Car> cars) {StaticFactory.cars = cars;}public static Car getCar(Integer id){return cars.get(id);}
}
StaticFactoryTest
package com.chenny.test;import com.chenny.entity.Car;
import com.chenny.factory.InstanceCarFactory;
import com.chenny.factory.StaticFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class StaticFactoryTest {public static void main(String[] args) {/*Ioc方法*/ApplicationContext applicationContext = new ClassPathXmlApplicationContext("factory.xml");Car car = (Car) applicationContext.getBean("car");System.out.println(car);/*传统做法*/Car car = StaticFactory.getCar(1);System.out.println(car);}
}
返回本知识点头部
实例⼯⼚⽅法
InstanceCarFactory
package com.chenny.factory;import com.chenny.entity.Car;import java.util.HashMap;
import java.util.Map;public class InstanceCarFactory {private Map<Integer, Car> carMap;public InstanceCarFactory() {carMap = new HashMap<Integer, Car>();carMap.put(1,new Car(1,"奔驰"));carMap.put(2,new Car(2,"宝马"));carMap.put(3,new Car(3,"幻影"));}public Car getCar(Integer id){return carMap.get(id);}
}
InstanceFactoryTest
package com.chenny.test;import com.chenny.entity.Car;
import com.chenny.factory.InstanceCarFactory;
import com.chenny.factory.StaticFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class StaticFactoryTest {public static void main(String[] args) {/*传统做法*/InstanceCarFactory instanceCarFactory = new InstanceCarFactory();Car car1 = instanceCarFactory.getCar(1);System.out.println(car1);/*Ioc方法*/ApplicationContext applicationContext = new ClassPathXmlApplicationContext("factory.xml");Car car = (Car) applicationContext.getBean("car2");System.out.println(car);}
}
返回本知识点头部
返回顶层
Ioc自动装载
Spring框架提供了一种更加简便的方式:自动装载,不需要手动配置property,IOC容器会根据bean的配置自动选择bean完成依赖注入(DI)。
- 自动装载有两种方式:
- byName:通过属性名自动装载。
- byType:通过属性对应的数据类型自动装载。
autowire.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"><!--创建person对象时,没有在property中配置car属性所以IOC容器会自动进行装载autowire="byName"表示通过匹配属性名的方式去装载对应的beanPerson实体类中有car属性,所以就将的bean注入到person中。
--><bean id="p1" class="com.test.entity.Person" autowire="byName"> <property name="id" value="1"></property><property name="name" value="ZhangSan"></property></bean><bean id="car1" class="com.test.entity.StaticCarFactory" factory-method="getCar"><constructor-arg value="1"></constructor-arg></bean><!-- byType即通过属性的数据类型来配置。关键字:autowire="byType"--><bean id="p2" class="com.test.entity.Person" autowire="byType"> <property name="id" value="1"></property><property name="name" value="张三"></property></bean><bean id="car2" class="com.test.entity.StaticCarFactory" factory-method="getCar"><constructor-arg value="1"></constructor-arg></bean></beans>
Person
//先创建一个实体类,并且生成setter/getter方法和toString方法
public class Person {private int id;private String name;private Car car;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Car getCar() {return car;}public void setCar(Car car) {this.car = car;}@Overridepublic String toString() {return "Person [id=" + id + ", name=" + name + ", car=" + car + "]";}}
Car
package com.chenny.entity;public class Car {private Integer id;private String brand;public Car() {}public Car(Integer id, String brand) {this.id = id;this.brand = brand;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getBrand() {return brand;}public void setBrand(String brand) {this.brand = brand;}@Overridepublic String toString() {return "Car{" +"id=" + id +", brand='" + brand + '\'' +'}';}
}
注意
- 使用了byType进行自动装载,如果spring的配置文件中配置了两个Car的bean,但是IOC容器不知道应该将哪一个bean装载到person对象中,因此可能会报错。所以在使用byType进行自动装载时,spring的配置文件中只能配置一个Car的bean才能使用byType。
- 通过property标签手动进行属性的注入优先级更高,若自动注入和手动配置两种方式同时存在,则以property的配置为主。所以在日常的代码编写过程中,尽量避免的使用byType去自动装配。
返回顶层
基于注解的开发
IoC 的实现⽅式:基于 XML 配置⽂件、基于注解
基于xml的实现
基于注解的实现
基于xml的实现
controller
package com.chenny.controller;import com.chenny.service.UserService;
import entity.User;public class UserController {private UserService userService;public void setUserService(UserService userService) {this.userService = userService;}public User findById(Integer id){return userService.findById(id);}
}
Service
package com.chenny.service.impl;import com.chenny.reponsitory.UserReponsitory;
import com.chenny.service.UserService;
import entity.User;public class UserServiceImpl implements UserService {private UserReponsitory userReponsitory;public void setUserReponsitory(UserReponsitory userReponsitory) {this.userReponsitory = userReponsitory;}@Overridepublic User findById(Integer id) {return userReponsitory.findById(id);}
}
Reponsitory
package com.chenny.reponsitory.impl;import com.chenny.reponsitory.UserReponsitory;
import entity.User;import java.util.HashMap;
import java.util.Map;public class UserReponsitoyImpl implements UserReponsitory {private static Map<Integer,User> userMap;public static void setUserMap(Map<Integer, User> userMap) {UserReponsitoyImpl.userMap = userMap;}static {userMap = new HashMap<Integer,User>();userMap.put(1,new User(1,"张三","123213"));userMap.put(2,new User(2,"李四","1232233"));}@Overridepublic User findById(Integer id) {return userMap.get(id);}
}
spring.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="userController" class="com.chenny.controller.UserController"><property name="userService" ref="userService"></property></bean><bean id="userService" class="com.chenny.service.impl.UserServiceImpl"><property name="userRepository" ref="userRepository"></property></bean><bean id="userRepository" class="com.chenny.repository.impl.UserRepositoryImpl"></bean>
</beans>
基于注解的实现
- 创建 bean
- 完成 DI
具体操作
- 将 UserController、 UserService、 UserRepository 扫描到 IoC 容器中。
- 在类中设置注解完成依赖注⼊。
@Controller
@Service
@Repository
@Resource
@Component
@Autowire:默认是通过 byType 完成⾃自动装载,如果要改为 byName,需要追加 @Qualifier,并注明⽬目标 bean 的 name。
Controller
package com.chenny.controller;import com.chenny.service.UserService;
import entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;@Controller("userController")
public class UserController {@Autowiredprivate UserService userService;public void setUserService(UserService userService) {this.userService = userService;}public User findById(Integer id){return userService.findById(id);}
}
Service
package com.chenny.service.impl;import com.chenny.reponsitory.UserReponsitory;
import com.chenny.service.UserService;
import entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class UserServiceImpl implements UserService {@Autowiredprivate UserReponsitory userReponsitory;public void setUserReponsitory(UserReponsitory userReponsitory) {this.userReponsitory = userReponsitory;}@Overridepublic User findById(Integer id) {return userReponsitory.findById(id);}
}
Reponsitory
package com.chenny.reponsitory.impl;import com.chenny.reponsitory.UserReponsitory;
import entity.User;
import org.springframework.stereotype.Repository;import java.util.HashMap;
import java.util.Map;@Repository
public class UserReponsitoyImpl implements UserReponsitory {private static Map<Integer,User> userMap;public static void setUserMap(Map<Integer, User> userMap) {UserReponsitoyImpl.userMap = userMap;}static {userMap = new HashMap<Integer,User>();userMap.put(1,new User(1,"张三","123213"));userMap.put(2,new User(2,"李四","1232233"));}@Overridepublic User findById(Integer id) {return userMap.get(id);}
}
Test
package com.chenny.test;import com.chenny.controller.UserController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class Test {public static void main(String[] args) {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");UserController userController = (UserController) applicationContext.getBean("userController");System.out.println(userController.findById(1));}
}
spring.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"xmlns:p="http://www.springframework.org/schema/p"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
"><!-- 将类扫描到 IoC 容器中 --><context:component-scan base-package="com.chenny"></context:component-scan></beans>
返回顶层
Spring AOP
Aspect Oriented Programming ⾯向切⾯编程, OOP ⾯向对象编程,将程序中所有参与模块都抽象成对象,然后通过对象之间的相互调⽤完成需求。
AOP 是 OOP 的⼀个补充,是在另外⼀个维度上抽象出对象,具体是指程序运⾏时动态地将⾮业务代码切⼊到业务代码中,从⽽实现代码的解耦合,将⾮业务代码抽象成⼀个对象,对该对象进⾏编程就是⾯向切⾯编程思想。
AOP的优点
- ⼤⼤降低模块之间的耦合性
- 提⾼代码的维护性
- 提⾼代码的复⽤性
- 集中管理⾮业务代码,便于维护
- 业务代码不受⾮业务代码的影响,逻辑更加清晰
Cal
package com.chenny.aop;public interface Cal {public int add(Integer numA,Integer numB);public int sub(Integer numA,Integer numB);public int mul(Integer numA,Integer numB);public int div(Integer numA,Integer numB);
}
CalImpl
package com.chenny.aop;public class CalImpl implements Cal{@Overridepublic int add(Integer numA, Integer numB) {int result = numA + numB;return result;}@Overridepublic int sub(Integer numA, Integer numB) {int result = numA - numB;return result;}@Overridepublic int mul(Integer numA, Integer numB) {int result = numA * numB;return result;}@Overridepublic int div(Integer numA, Integer numB) {int result = numA / numB;return result;}
}
MyInvocationHandler
package com.chenny.aop;import java.lang.reflect.Array;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;public class MyInvocationHandler implements InvocationHandler {private Object object = null;//返回代理对象public Object bind(Object object){this.object = object;return Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces(),this);}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println(method.getName() + "参数是:" + Arrays.toString(args));Object result = method.invoke(this.object,args);System.out.println(method.getName() + "结果是:" + result);return result;}
}
CalTest
package com.chenny.test;import com.chenny.aop.Cal;
import com.chenny.aop.CalImpl;
import com.chenny.aop.MyInvocationHandler;public class CalTest {public static void main(String[] args) {Cal cal = new CalImpl();MyInvocationHandler myInvocationHandler = new MyInvocationHandler();Cal proxy = (Cal) myInvocationHandler.bind(cal);System.out.println(proxy.add(10,3));System.out.println(proxy.sub(10,3));System.out.println(proxy.div(10,3));System.out.println(proxy.mul(10,3));}
}
SpringAop
1、目标类
package com.chenny.aop;public class CalImpl implements Cal {public int add(int num1, int num2) {int result = num1 + num2;return result;}public int sub(int num1, int num2) {int result = num1-num2;return result;}public int mul(int num1, int num2) {int result = num1*num2;return result;}public int div(int num1, int num2) {int result = num1/num2;return result;}
}
2、创建切面类 LoggerAspect
package com.chenny.aspect;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;import java.util.Arrays;@Aspect
@Component
public class LoggerAspect {@Before(value = "execution(public int com.chenny.aop.CalImpl.*(..))")public void before(JoinPoint joinPoint){//获取方法名String name = joinPoint.getSignature().getName();//获取参数列表String atgs = Arrays.toString(joinPoint.getArgs());System.out.println(name + "参数列表是" + atgs);}@AfterReturning(value = "execution(public int com.chenny.aop.CalImpl.*(..))",returning = "result")public void afterReturning(JoinPoint joinPoint,Object result){System.out.println(joinPoint.getSignature().getName() + "结果为: " +result);}@After(value = "execution(public int com.chenny.aop.CalImpl.*(..))")public void after(JoinPoint joinPoint){System.out.println(joinPoint.getSignature().getName() + "业务代码执行完毕!");}@AfterThrowing(value = "execution(public int com.chenny.aop.CalImpl.*(..))",throwing ="e")public void afterThrowing (JoinPoint joinPoint,Exception e){System.out.println(joinPoint.getSignature().getName() + "方法抛出异常!" + e);}}
3、将目标类和切面类交给 IoC 容器管理,IoC 容器会自动创建实例化对象,结合 JDK 动态代理,自动实现 InvocationHandler 接口,整合完成业务代码和非业务代码的解耦合。
<?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:aop="http://www.springframework.org/schema/aop"xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsd"><!-- 自动扫描 --><context:component-scan base-package="com.chenny"></context:component-scan><!-- 为目标类自动生成代理对 --><aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
- context:component-scan 将 com.southwind 包中的所有类扫描到 IoC 容器中,需要结合 @Component 注解完成。
- aop:aspectj-autoproxy Spring 会结合切面类和目标类自动生成动态代理对象,代理对象完成非业务代码(日志打印)。
AOP 核心概念
- 切面对象:根据切面抽象出来的对象,CalImpl 所有方法中需要加入日志的部分,抽象成一个切面对象 LoggerAspect。
- 通知:切面对象的具体代码,即非业务代码,LoggerAspect 打印日志的各种操作。
- 目标:被切割的对象,CalImpl。
- 代理:切面对象,通知,目标混合之后的产物,Spring 通过 JDK 动态代理创建,真正执行代码的对象。
- 连接点:需要被横切的位置,即通知要插入业务代码的具体位置。
同时给一个目标添加多个切面,执行顺序,实现 org.springframework.Ordered 接口,ordered 越小最先执行。
返回顶层
返回目录
Spring框架汇总(大学生的天堂 码农的圣殿)相关推荐
- 开发无框架单页面应用 — 老码农的祖传秘方
什么是单页面应用(SPA)? 维基百科上的描述是这样的: JavaScript 1 2 3 "A single-page application (SPA), is a web applic ...
- Spring框架面试典籍30+ | 大别山码将
Spring 什么是Spring框架 Spring 是⼀种轻量级(从大小与开销两方面)开发框架,目的是用于简化企业应用程序的开发,它使得开发者只需要 关心业务需求.常见的配置方式有三种:基于 XML ...
- 十个基于Python的BBS论坛类开源web框架汇总(附源码地址)
1.LBForum LBForum是用django开发的论坛系统,LBForum主要注重部署的方便性和易用性,功能方面目前还比较简单. LBForum的开发尽量遵照Django可复用app原则,因此即 ...
- python web论坛_十个基于Python的BBS论坛类开源web框架汇总(附源码地址)
1.LBForum LBForum是用django开发的论坛系统,LBForum主要注重部署的方便性和易用性,功能方面目前还比较简单. LBForum的开发尽量遵照Django可复用app原则,因此即 ...
- python论坛系统源码_十个基于Python的BBS论坛类开源web框架汇总(附源码地址
1.LBForum LBForum是用django开发的论坛系统,LBForum主要注重部署的方便性和易用性,功能方面目前还比较简单. LBForum的开发尽量遵照Django可复用app原则,因此即 ...
- python bbs论坛_十个基于Python的BBS论坛类开源web框架汇总(附源码地址)
1.LBForum LBForum是用django开发的论坛系统,LBForum主要注重部署的方便性和易用性,功能方面目前还比较简单. LBForum的开发尽量遵照Django可复用app原则,因此即 ...
- java毕业设计基于spring框架的论坛网站项目设计和源码
一.主题 榴莲社区--java开发基于spring框架的论坛网站,基于spring框架的论坛网站项目设计和项目 源 码 免 费下 载 链 接 如 下: 毕业设计项目基于spring框架的论坛网站源码 ...
- spring cloud是什么时候流行的_老司机给我们解读 Spring Boot 最流行的 16 条实践 - 码农突围
Spring Boot 是最流行的用于开发微服务的 Java 框架.在本文中,我将与你分享自 2016 年以来我在专业开发中使用 Spring Boot 所采用的最佳实践.这些内容是基于我的个人经验和 ...
- 2020年,大学生该如何成为一名初级码农
文章目录 入学伊始 大一前期 加入工作室 大一末期 工作室是怎么样的 初入工作室 工作室培训 工作室换代 项目经验 项目开发对我的帮助 没有项目经验怎么办? 办法总是有的 回归主题 一点点建议.... ...
- 写给立志做程序员(码农)的大学生
作者: 果冻虾仁 来源: CSDN 发布时间: 2017-08-10 23:08 阅读: 32769 次 推荐: 158 原文链接 [收藏] 写给立志做码农的大学生 确定方向 选择比努 ...
最新文章
- 剑指offer:面试题05. 替换空格
- redis Could not connect to Redis at 127.0.0.1:6379: Connection refused 问题解决
- 如何使用Git解决“错误:错误索引 - 致命:索引文件损坏”
- HDLBits答案(10)_D触发器、同步与异步复位、脉冲边沿检测
- vue项目做微信分享功能
- Truffle测试框架
- linux zip命令收藏
- windows配置caffe及matlab/python接口编译和调用(cpu/gpu)
- 汽车之家广告营销案例分析PPT模板
- 如何在springboot中返回jsp页面
- 关于京东商城在宜宾开通货到付款的随想
- 文件名称: 项目利用循环求和 、分数的累加、乘法表
- python in arcgis_终于晓得arcgis-python入门教程
- 产品经理如何进行数据分析?看这一篇文章就够了
- 从卷积神经网络(CNN)到图卷积神经网络(GCN)详解
- 格式化数据恢复怎么做?超实用的3种方法在这!
- 哈勃深空场以及星系合并的宇宙瑰丽景象
- ArcGIS 从DSM中提取高程点
- 苹果mac能安装计算机题库吗,如果苹果系统能安装在普通PC电脑上,你装么?
- 来,跟我一起 ,自研多端错误监控平台(完整版)