文章目录
-
- spring分层架构
- spring核心
-
- ioc(控制反转)
-
- 1)**接下来是代码示例:**接下来是代码示例:)
- 2)**ioc容器的使用过程**ioc容器的使用过程)
- 3)ioc中的bean管理ioc中的bean管理)
- 4)实例化bean的三种方式实例化bean的三种方式)
- aop(面向切面开发)
- 定义
- 优势
- AOP底层原理
- AOP相关的术语
- AOP入门
- aop注解开发
- aop纯注解开发
spring分层架构
表现层
springmvc
2.
服务层(业务层)
spring ioc
3.
持久层
mybatis
mybatis plus
hibernite
互联网项目,多ssm结构
spring核心
ioc(控制反转)
ioc将对象的创建权利交给spring框架,底层实际上是使用反射实现的。降低程序的耦合度
1)接下来是代码示例:
-
创建一个空的maven项目
-
引入一些基本依赖
xml
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
-
准备实体类
java// 创建一个接口 public interface UserService { public void hello(); } // 创建一个实体类 public class UserServiceImpl implements UserService { @Override public void hello() { System.out.println("Hello, world!"); } }
-
准备配置文件
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="us" class="实体类的路径"></bean> </beans>
-
在test中测试
java// 常规方法 @Test public void testUser() { // TODO: write test cases for UserService UserService userService = new UserServiceImpl(); userService.hello(); } // 基于ioc容器管理的方法,ioc是一个map key是对象的标识,value是ioc创建的对象 @Test public void run1() { // 创建spring ioc工厂 ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); // 获取bean UserService userService = (UserService) ac.getBean("us"); userService.hello(); }
上面就是一个关于ioc容器的示例
2)ioc容器的使用过程
ApplicationContext接口,这个工厂接口,使用这个接口就可以获得相应的Bean对象,该对象下有两个实现类
- ClassPathXmlApplicationContext:加载类路径下的spring配置文件(常用)
- FileSystemXmlApplicationContext:加载本地磁盘下的spring配置文件(让项目和配置文件分离管理,不常用)
3)ioc中的bean管理
- id属性:bean的别名,取名要求:必须要字母开头,可以使用数字,连字符,下划线,字母,不能出现特殊字符
- class属性:bean对象的全路径
- scope属性: bean对象的作用范围
- singleton:单例(默认)生命周期和配置文件一样
- prototype:多例,不是加载配置文件时创建,而是在获取实例对象时创建
- request: 多例,不常用,应用于web项目中,每个请求都会创建一个新的实例对象
- session:多例,不常用,应用于web项目中,向一个http session中共享一个实例
- init-method:bean对象创建时可以配置一个指定的方法自动调用
- destory-method:bean对象销毁时可以配置一个指定的方并自动调用
4)实例化bean的三种方式
-
默认是无参的构造方法
xml<bean id="us" class="实体类的路径"></bean>
-
静态工厂实例化方法(好处是可以自己编写业务逻辑)
准备一个静态工厂类
javapublic class StaticFactory { public static UserService createUser() { // 编写业务逻辑 // ...... return new UserServiceImpl(); } }
在xml配置文件中使用
xml<bean id="us1" class="com.qc.util.StaticFactory" factory-method="createUser"></bean>
-
实例化工厂实例化方式
准备一个可以实例化的类
javapublic class DFactory { public UserService createUser() { // 编写业务逻辑 return new UserServiceImpl(); } }
在xml配置文件中使用
xml<bean id="factory" class="com.qc.util.DFactory"></bean> <bean id="us2" factory-bean="factory" factory-method="createUser"></bean>
aop(面向切面开发)
定义
是一种编辑的范式,是OOP的延续,也是Spring框架中函数编程的一种衍生范式,利用AOP可以对业务的各个部分进行隔离,从而似的业务逻辑各部分之间的耦合度降低,提高了程序的重用性,同时提高了开发的效率,AOP采用横向抽取机制,取代了传统纵向继承体系。
优势
- 运行期间,不修改源代码的情况下,对已有的方法进行增强,减少重复代码
- 提高开发效率
- 方便维护
AOP底层原理
- 如果使用接口,则使用JDK动态代理技术,如果没有使用接口,使用的是继承则是cglib代理
AOP相关的术语
- Joinpoint(连接点)所谓连接点是指那些被连接到的点,在spring中,这些带点指的是方法,因为spring只支持方法类型的节点
- Pointcut(切入点)所谓切入点是我们要对哪些Joinpoint进行拦截的定义
- Advice(通知\通知)所谓通知就是指,拦截到Joinpoint之后所要做的情况就就是通知,通知分为,前置通知,后置通知,异常通知,最终通知,环绕通知(切面类中要完成的功能)
- Target(目标对象)代理的目标对象
- Weaving(织入)是指把增强应用到目标对象来创建新的代理对象的过程
- Proxy(代理)一个类被AOP织入增强后,就产生一个结果代理类
- Aspect(切面)是切入点+通知的结合,是自己编写和配置
AOP入门
-
导入坐标依赖
pom.xml<dependency> <groupId>aopalliance</groupId> <artifactId>aopalliance</artifactId> <version>1.0</version> </dependency> <!--Spring Aspects--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>5.0.2.RELEASE</version> </dependency> <!--aspectj--> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.3</version> </dependency>
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" 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"> </beans>
-
编写spirng配置文件中AOP的配置部分
applicationContext.xml<!-- bean管理--> <bean id="us" class="com.qc.service.impl.UserServiceImpl"/> <bean id="myAspect" class="com.qc.util.MyAspect"/> <!-- 配置aop--> <aop:config> <!-- 配置切面--> <aop:aspect ref="myAspect"> <!-- 前缀通知--> <aop:before method="log1" pointcut="execution(public void com.qc.service.impl.UserServiceImpl.save())"/> <!-- 后置通知--> <aop:after-returning method="log2" pointcut="execution(public void com.qc.service.impl.UserServiceImpl.save())"/> <!-- 异常通知--> <aop:after-throwing method="log3" pointcut="execution(public void com.qc.service.impl.UserServiceImpl.save())"/> <!-- 最终通知--> <aop:after method="log4" pointcut="execution(public void com.qc.service.impl.UserServiceImpl.save())"/> <!-- 环绕通知--> <aop:around method="aroundLog" pointcut="execution(public void com.qc.service.impl.UserServiceImpl.save())"/> </aop:aspect> </aop:config>
javaimport org.aspectj.lang.ProceedingJoinPoint; public class MyAspect { // 自定义切面类 = 切入点+通知 //通知 public void log1() { System.out.println("前置增强的"); } public void log2() { System.out.println("后置增强的"); } public void log3() { System.out.println("异常增强的"); } public void log4() { System.out.println("最终增强的"); } public void aroundLog(ProceedingJoinPoint point) { try { log1(); point.proceed(); // 目标方法调用 log2(); } catch (Throwable e) { e.printStackTrace(); log3(); } finally { log4(); } } }
注意环绕通知使用的接口
通知类型
- 前置通知:目标方法执行前进行增强
- 后置通知:目标方法执行后进行增强
- 异常通知:目标方法出现异常后进行增强
- 最终通知:目标方法无论是否异常都进行增强
- 环绕通知:目标方法执行前后,都进行增强,不过需要自己书写
切入点表达式
- execution([修饰符] 返回值 包名.类名.方法名(参数))
- 修饰符可以省略不写
- 返回值类型不能省略,根据方法来编写返回值,可以用星号来代替
- 包名类型方法名是不能省略的,但是可以用星号来代替,也可以部分代替
- 参数如果是一个可以用星号来代替,如果是多个可以使用两个点
因此比较通用的表达式:
execution( com.qc .*.Service.save(...))
aop注解开发
给切面添加@Aspect,编写增强的方法,使用通知类型注解声明
xml
<!-- 开启注解扫描-->
<context:component-scan base-package="com.qc"/>
<!-- 开启自动代理-->
<aop:aspectj-autoproxy/>
java
@Aspect
@Component
public class MyAspect {
// 自定义切面类 = 切入点+通知
//通知
@Before("execution(* com.qc.*.*.*ServiceImpl.save(..))")
public void log1() {
System.out.println("前置增强的");
}
@AfterReturning("execution(* com.qc.*.*.*ServiceImpl.save*(..))")
public void log2() {
System.out.println("后置增强的");
}
@AfterThrowing("execution(* com.qc.*.*.*ServiceImpl.save*(..))")
public void log3() {
System.out.println("异常增强的");
}
@After("execution(* com.qc.*.*.*ServiceImpl.save*(..))")
public void log4() {
System.out.println("最终增强的");
}
@Around("execution(* com.qc.*.*.*ServiceImpl.save*(..))")
public void aroundLog(ProceedingJoinPoint point) {
try {
log1();
point.proceed(); // 目标方法调用
log2();
} catch (Throwable e) {
e.printStackTrace();
log3();
} finally {
log4();
}
}
}
在每个方法上使用注解进行配置,和配置文件类似
通知类型注解:
- @Before 前置注解
- @AfterReturning 后置注解
- @AfterThrowing 异常注解
- @After 最终注解
- @Round 环绕注解
注意:在配置文件中开启自动代理
aop纯注解开发
@EnableAspectJAutoProxy 开启自动代理
3.
Di(依赖注入)
依赖注入:在spring框架负责创建bean对象时,动态的将对象注入到其他的bean对象中
1)属性的set方法注入值的方式
-
声明变量并在需要依赖注入的地方设置set方法
-
在xml文件中配置该变量的值
xml<bean id="us" class="com.qc.service.impl.UserServiceImpl"> <property name="userDao" ref=""></property> <property name="name" value=""></property> </bean>
参数说明:如果property中的是一个简单类型(基本类型和字符串),那么就使用value,否则就使用ref
2)构造方法赋值的方法
-
在需要的地方添加构造方法
-
在配置文件中使用带参数的构造方法传参
xml<bean id="userDao" class="com.qc.dao.impl.UserDaoImpl"></bean> <bean id="us" class="com.qc.service.impl.UserServiceImpl"> <constructor-arg name="userDao" ref="userDao"></constructor-arg> </bean>
-
其他类型的参数传参
准备一个java类
javapublic class CollectionBean { private String[] strs; private List<String> list; private Map<String, String> map; private Properties properties; public Properties getProperties() { return properties; } public void setProperties(Properties properties) { this.properties = properties; } public Map<String, String> getMap() { return map; } public void setMap(Map<String, String> map) { this.map = map; } public String[] getStrs() { return strs; } public List<String> getList() { return list; } public void setList(List<String> list) { this.list = list; } public CollectionBean() { } public void setStrs(String[] strs) { this.strs = strs; } public CollectionBean(String[] strs) { this.strs = strs; } }
-
不可变数组
xml<bean id="co" class="com.qc.service.CollectionBean"> <property name="strs"> <array> <value>小美</value> <value>小张</value> <value>小王</value> </array> </property> </bean>
-
可变集合
xml<bean id="co" class="com.qc.service.CollectionBean"> <property name="list"> <list> <value>张三</value> <value>李四</value> <value>王五</value> </list> </property> </bean>
-
map集合
xml<bean id="co" class="com.qc.service.CollectionBean"> <property name="map"> <map> <entry key="name" value="zhangsan"></entry> <entry key="age" value="18"></entry> </map> </property> </bean>
-
其他类型
xml<bean id="co" class="com.qc.service.CollectionBean"> <property name="properties"> <props> <prop key="username">zhangsan</prop> <prop key="password">1234</prop> </props> </property> </bean>
-
多配置文件
-
在配置文件中使用
xml<import resource="applicationContext.xml"></import>
-
创建工厂时直接加载多个配置文件
javaApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml","applicationContext1.xml");
<props>
<prop key="username">zhangsan</prop>
<prop key="password">1234</prop>
</props>
</property>
</bean>
```
多配置文件
-
在配置文件中使用
xml<import resource="applicationContext.xml"></import>
-
创建工厂时直接加载多个配置文件
javaApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml","applicationContext1.xml");