Spring注入和AOP

Spring注入&AOP

注入

Maven里面注入Spring

创建最基本的Maven项目,进行依赖注入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.ifueen</groupId>
<artifactId>spring-day02</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!--Spring的核心包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<!--Context包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<!--aop的包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<!--切面的一个包(织入)-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.8</version>
</dependency>

<!-- Spring的测试包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.2.5.RELEASE</version>
<!--scope:范围,只能在test包中使用-->
<!--<scope>test</scope>-->
</dependency>
<!--junit的测试支持-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>

</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/test/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>

</project>

通过构造方法注入参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?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="mybean" class="com.ifueen._02constructor.MyBean">

<!-- 通过索引配置-->
<!--<constructor-arg index="0" value="罗素"/>
<constructor-arg index="1" value="3"/>-->

<!-- 通过name配置 -->
<!--<constructor-arg name="age" value="30"/>
<constructor-arg name="name" value="爱伦坡"/>-->

<!-- 通过类型进行配置-->
<!--<constructor-arg type="java.lang.String" value="狄更斯"/>
<constructor-arg type="java.lang.Integer" value="45"/>-->

<!-- 直接根据参数顺序进行配置,注意!参数顺序一定要相对应-->
<constructor-arg value="萨特"/>
<constructor-arg value="30"/>
</bean>
</beans>

集合&数组&其他属性的注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
<?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="otherBean" class="com.ifueen._03rest.OtherBean"/>
<bean id="mybean" class="com.ifueen._03rest.MyBean">

<!-- 一般简单的属性 -->

<property name="id" value="1"/>
<property name="name" value="山泥若"/>
<property name="sex" value="true"/>
<property name="salary" value="797979"/>

<!-- 数组 -->
<property name="arrays">
<array>
<value>爱伦坡</value>
<value>伏尔泰</value>
<value>罗素</value>
</array>
</property>

<!-- List集合 -->
<property name="list">
<list>
<value>娄烨</value>
<value>王家卫</value>
<value>李安</value>
</list>
</property>

<!-- set集合 -->
<property name="set">
<set>
<value>诺兰</value>
<value>昆汀</value>
<value>斯皮尔伯格</value>
</set>
</property>

<!-- List集合OtherBean-->
<property name="otherBeanList">
<list>
<!-- 内部Bean -->
<bean class="com.ifueen._03rest.OtherBean"/>
<bean class="com.ifueen._03rest.OtherBean"/>
<!-- 外部引用 -->
<ref bean="otherBean"/>
<ref bean="otherBean"/>
</list>
</property>

<!-- Set集合OtherBean-->
<property name="otherBeanSet">
<list>
<!-- 内部Bean -->
<bean class="com.ifueen._03rest.OtherBean"/>
<bean class="com.ifueen._03rest.OtherBean"/>
<!-- 外部引用 -->
<ref bean="otherBean"/>
<ref bean="otherBean"/>
</list>
</property>

<!-- 简写方式 -->
<property name="props1">
<value>
drivenClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///jpa
username=root
password=123456
</value>
</property>

<!-- 标准写法 -->
<property name="props2">
<props>
<prop key="drivenClassName">com.mysql.jdbc.Driver</prop>
<prop key="url">jdbc:mysql:///hello</prop>
<prop key="username">root</prop>
<prop key="password">123456</prop>
</props>
</property>

<!-- Map集合 -->
<property name="hashMap">
<map>
<entry key="电影" value="2001太空漫步"/>
<entry key="导演" value="库布里克"/>
</map>
</property>
</bean>


</beans>

使用全注解

使用全注解的方式和之前SpringMVC的使用方式一模一样

1
2
3
4
5
6
7
8
9
10
<?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"
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">
<context:component-scan base-package="com.ifueen._04auto"/>
</beans>

只需要将扫描包路径配置好,然后写三层架构即可

AOP(面向切面编程)

概述

定义:面向切面编程(面向方面编程)

咱们的编程语言从原始机器语言 到过程语言 再到面向对象,从始至终的目的就是为了让代码再加灵活,再加容易让人理解,构建代码更加简单。

AOP的使用只存在于一些特定的场合(具有横切逻辑的应用场合),横切逻辑这个解释可能比较抽象,咱们说得再具体一点,AOP可以用于事务管理,日志管理,性能监测等地方

面试题:Spring是如何实现AOP?

Spring是使用代理模式来实现AOP的

代理模式分两种:静态代理和动态代理

静态代理太过笨重,一般不太使用

动态代理

Spring提供了两种方案:JDK和CGLTB

如果目标对象使用了接口就让JDK来进行代理

如果目标对象没有使用接口就让CGLTB来进行代理

使用XML配置实现AOP

首先定义自定义的事务类(伪事务类)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package com.ifueen._05xmlaop;

import org.aspectj.lang.ProceedingJoinPoint;

/**
* 自己准备的一个事务
*/
public class TxManager {

public void begin(){
System.out.println("开启事务");
}
public void commit(){
System.out.println("提交事务");
}
public void rollback(Throwable e){
System.out.println("回滚事务,异常的原因为"+e.getMessage());
}
public void close(){
System.out.println("关闭资源");
}

public void around(ProceedingJoinPoint point){
/*System.out.println(point.getArgs()); //参数
System.out.println(point.getSignature()); //获取方法的签名
System.out.println(point.getTarget().getClass());//真实目标对象
System.out.println(point.getThis().getClass()); //代理对象*/
try {
//开启事务
begin();
//这里执行我们自己的代码
point.proceed();
//提交事务
commit();
} catch (Throwable throwable) {
//回滚
rollback(throwable);
throwable.printStackTrace();
}finally {
//关闭
close();
}
}


}

然后进行xml配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="myBeanService" class="com.ifueen._05xmlaop.service.impl.MyBeanServiceImpl"></bean>
<bean id="txManager" class="com.ifueen._05xmlaop.TxManager"></bean>

<!-- 配置AOP -->
<aop:config>
<!--
id:切点的名称
execution是一个表达式,去执行方法
*:代表任意返回值
com.ifueen._05xmlaop.service:对应的包
I*Service:对应的类
*:所有的方法
(..):方法里面任意参数
-->
<aop:pointcut id="pointcut" expression="execution(* com.ifueen._05xmlaop.service.I*Service.*(..))"/>

<aop:aspect ref="txManager">
<!-- 前置通知 -->
<!--<aop:before method="begin" pointcut-ref="pointcut"></aop:before>-->
<!-- 后置通知 -->
<!--<aop:after-returning method="commit" pointcut-ref="pointcut"></aop:after-returning>-->
<!-- 异常通知,如果要抓取异常的话需要在这里也要设置 -->
<!--<aop:after-throwing method="rollback" pointcut-ref="pointcut" throwing="e"></aop:after-throwing>-->
<!-- 最终通知 -->
<!--<aop:after method="close" pointcut-ref="pointcut"></aop:after>-->
<!-- 环绕通知 里面可以自定义-->
<aop:around method="around" pointcut-ref="pointcut"></aop:around>
</aop:aspect>
</aop:config>


</beans>

使用注解配置AOP

xml配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?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"
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.ifueen._06annoaop"></context:component-scan>
<!-- 支持AOP注解 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

自定义的事务类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package com.ifueen._06annoaop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
* 注解实现的事务
*/
@Component
@Aspect //AOP的类注解
public class TxManager {

//设置切点
@Pointcut("execution(* com.ifueen._06annoaop.service.I*Service.*(..))")
public void pointcut(){}

//前置通知
/*@Before("pointcut()")*/
public void begin(){
System.out.println("开启事务");
}
//后置通知
/*@AfterReturning("pointcut()")*/
public void commit(){
System.out.println("提交事务");
}
//异常通知
/*@AfterThrowing(pointcut = "pointcut()",throwing = "e")*/
public void rollback(Throwable e){
System.out.println("回滚事务,异常的原因为"+e.getMessage());
}
//最终通知
/*@After("pointcut()")*/
public void close(){
System.out.println("关闭资源");
}

//如果要使用环绕通知,需关闭前面的注解,不然可能引起冲突
@Around("pointcut()")
public Object around(ProceedingJoinPoint point){
Object object = null;
try {
//开启事务
begin();
//这里执行我们自己的代码
object = point.proceed();
//提交事务
commit();
} catch (Throwable throwable) {
//回滚
rollback(throwable);
throwable.printStackTrace();
}finally {
//关闭
close();
}
return object;
}


}
❤赏点钱让我买杯快乐水8❤