1. 对于AOP的理解
想要理解AOP,必须先理解动态代理,想要理解动态代理,必须理解静态代理
1.1静态代理
此处租房为接口,真实角色为使用代理之前的实现该接口的某一应用层,而代理角色与真实角色一样实现该接口,但是它能在不改变真实角色这一应用层的基础上,起到该真实角色应用层相同的作用,并且在此基础上扩展增强功能。
租房接口
//租房
public interface Rent {
public void rent();
}
真实角色
//房东
public class Host implements Rent{
@Override
public void rent() {
System.out.println("房东要出租房子!");
}
}
代理角色
public class Proxy implements Rent{
private Host host;
public Proxy() {
}
public Proxy(Host host) {
this.host = host;
}
@Override
public void rent() {
seeHouse();
host.rent();
protocol();
fare();
}
// 看房
public void seeHouse()
{
System.out.println("中介带你看房");
}
// 收中介费
public void fare()
{
System.out.println("收中介费");
}
// 签合同
public void protocol()
{
System.out.println("签租赁合同");
}
}
测试类
public class Client {
public static void main(String[] args) {
// 房东要租房子
Host host = new Host();
// 代理,中介帮房东租房子,但是代理角色一般会有一些附属操作
Proxy proxy = new Proxy(host);
// 你不用面对房东,直接找中介租房即可
proxy.rent();
}
}
1.2 动态代理
动态代理的功能更强于静态代理,虽然各个角色不变,但是动态代理可以代理多个类,只要这些类实现了同一个接口(是一类业务),这是静态代理做不到的。
重点了解两个类:Proxy:处理,生成得到代理类。InvocationHandler:调用处理程序,处理代理实例并返回结果。
此时接口与真实角色仍然不变(即在真实项目中原代码不变。)
代理类
利用getProxy()和invoke()(反射的应用?),在原真实角色的基础上的方法前后加入了其他的功能,这也是AOP的本质。
package com.yan.demo03;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//等会我们会用这个类,自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {
// 被代理的接口
private Rent rent;
public void setRent(Rent rent) {
this.rent = rent;
}
// 生成得到代理类
public Object getProxy()
{
return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(), this);
}
// 处理代理实例,并返回结果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 动态代理的本质,就是使用反射机制实现
seeHouse();
Object result = method.invoke(rent, args);
fare();
return result;
}
public void seeHouse()
{
System.out.println("中介带看房子");
}
public void fare()
{
System.out.println("收中介费");
}
}
测试类
package com.yan.demo03;
public class Client {
public static void main(String[] args) {
// 真实角色
Host host = new Host();
// 代理角色:现在没有
ProxyInvocationHandler pih = new ProxyInvocationHandler();
// 通过调用程序处理角色来处理我们要调用的接口对象!
pih.setRent(host);
Rent proxy = (Rent) pih.getProxy();//这里的proxy就是动态生成的,我们并没有写
proxy.rent();
}
}
1.3 AOP
由上面静态代理以及动态代理的例子可以看出,AOP其实是在整个项目纵向进行时横向切入某一应用层,并且在不改变该应用层代码的基础上,对其进行代理以及功能的增强。
2.使用Spring实现AOP
使用AOP织入,需要导入一个依赖包!
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
2.1 不同方式实现AOP,由基础到简单
方式一:使用Spring的API结构 【主要是SpringAPI接口实现】
方式二:自定义类来实现AOP 【主要是切面定义】
方式三:使用注解实现!
3. AOP的各个专业词
4. 使用Spring整合Mybatis
步骤:
1.导入相关jar包
junit
mybatis
mysql数据库
spring相关
aop织入
mybatis-spring【new】
注意我在这里导入mybatis-spring2.0.2依赖时会提示can not resolve SqlSessionFactoryBean(搞了一下午,就是因为依赖的版本不对,但是是跟着秦疆老师的视频所有依赖版本一样的,可能是IDEA版本和他不一样吧),在导入mybatis-spring2.0.5之后恢复正常
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<!-- Spring操作数据库的话,还需要一个spring-jdbc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.13</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.5</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
</dependency>
</dependencies>
为了避免Binding Exception(xml文件在java或者resources中可能会被自动过滤)
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
5. 利用AOP思想使用Spring处理Mybatis事务
声明式事务:AOP
【不同Propagation传播类型的事务属性,重点】
编程式事务:需要在代码中,进行事务的管理
<!-- 配置声明式事务-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<constructor-arg ref="dataSource"/>
</bean>
<!-- 结合AOP实现事务的织入-->
<!-- 配置事务通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!-- 给哪些方法配置事务-->
<!-- 配置事务的传播特性-->
<tx:attributes>
<tx:method name="add" propagation="REQUIRED"/>
<tx:method name="delete" propagation="REQUIRED"/>
<tx:method name="update" propagation="REQUIRED"/>
<tx:method name="query" read-only="true"/>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!-- 配置事务切入-->
<aop:config>
<aop:pointcut id="txPointCut" expression="execution(* com.yan.mapper.UserMapper.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>