SpringAOP的xml和注解两种实现方式
1、SpringAop的实现方案
Spring实现Aop有两种方案:JDK与CGLIB(Spring底层自动实现的)
点击此处可查看代理模式的代码实现
第一种方式:若目标对象实现了若干接口spring使用JDK的java.lang.reflect.Proxy类代理。
第二种方式:若目标对象没有实现任何接口,spring使用CGLIB库生成目标对象的子类。
注意事项:
1.对接口创建代理优于对类创建代理,因为会产生更加松耦合的系统。 对类代理是让遗留系统或无法实现接口的第三方类库同样 可以得到通知,这种方案应该是备用方案。
2.标记为final的方法不能够被通知。spring是为目标类产生子类。任何需要被通知的方法都被复写,将通知织入。final方法是不允许重写的。
2、maven导包
<!--引入spring需要的包-->
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<!--spring-aop-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<!--在配置文件里面用application-context-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<!--测试-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!--植入-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.8</version>
</dependency>
</dependencies>
<!--使用JDK1.8的配置-->
<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>
<!--加载xml-->
<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>
3、xml实现aop的方式
3.1项目结构
3.2 IUserService
package cn.itsource._08_springaop;
public interface IUserService {
public void save();
public void delete();
public void update();
}
3.3 UserviceImpl
package cn.itsource._08_springaop;
public class UserviceImpl implements IUserService {
@Override
public void save() {
System.out.println("save");
}
@Override
public void delete() {
System.out.println("delete");
}
@Override
public void update() {
System.out.println("update");
}
}
3.4 TxManager
package cn.itsource._08_springaop;
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 joinPoint){
//System.out.println(joinPoint.getArgs()); //参数
//System.out.println(joinPoint.getSignature()); //方法签名(这个方法的所有信息都有)
try {
begin();
joinPoint.proceed(); //执行对应的方法
commit();
} catch (Throwable e) {
rollback(e);
} finally {
close();
}
}
}
3.4 重点:SpringTest-context.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: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 class="cn.itsource._08_springaop.UserviceImpl" id="uservice"></bean>
<!--增强对象-->
<bean class="cn.itsource._08_springaop.TxManager" id="txManager"></bean>
<!--
aop配置
切点写接口类,它会自动切所有的实现类
*:任意返回值
*:所有的方法
(..):任意参数
before在切点之前运行
after-returning在切点之后运行
after-throwing异常抛出,
after最终通知
-->
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* cn.itsource._08_springaop.I*Service.*(..))"></aop:pointcut>
<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:aspect>
</aop:config>
</beans>
3.6 测试SpringTest
注意:xml的配置文件名前面与测试名一致,那么@ContextConfiguration不用配置xml路径
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class SpringTest {
@Autowired
private IUserService userService;
@Test
public void TestBean(){
userService.delete();
}
}
3.7 打印结果
开始事务...
delete
关闭事务...
提交事务...
4、全注解实现aop(通常使用)
4.1项目结构
4.2 IUserService
public interface IUserService {
public void save();
public void delete();
public void update();
}
4.3 UserviceImpl
@Service
public class UserviceImpl implements IUserService {
@Override
public void save() {
System.out.println("save");
}
@Override
public void delete() {
System.out.println("delete");
}
@Override
public void update() {
System.out.println("update");
}
}
4.4 SpringTest-context.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: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/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
">
<context:component-scan base-package="cn.itsource._09_aopanno"/>
<!--配置aop注解支持-->
<aop:aspectj-autoproxy />
</beans>
4.5 重点 TxManager
package cn.itsource._09_aopanno;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
/**
* 这是一个模拟的假事务
*/
@Component
@Aspect
public class TxManager {
@Pointcut("execution(* cn.itsource._09_aopanno.IUserService.*(..))")
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("关闭事务...");
}
}
4.6 测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class SpringTest {
@Autowired
private IUserService userService;
@Test
public void TestBean(){
userService.delete();
}
}
4.7 打印结果
开始事务...
delete
关闭事务...
提交事务...