引入依赖
<!--引入依赖-->
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.9</version>
</dependency>
<!--这是lombok依赖-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
<!--这是测试依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.3.9</version>
</dependency>
</dependencies>
配置文件Springconfig
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.biyi"/>
</beans>
不使用代理出现的问题
package com.biyi.service.implment;
import com.biyi.dao.Dao;
import com.biyi.service.UserService;
import com.biyi.user.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImplment implements UserService {
@Autowired
private Dao dao;
@Override
public void addUser(User user) {
System.out.println("每个方法都需要写这样相同的代码");
System.out.println("权限校验");
System.out.println("事务管理");
System.out.println("开启事务");
try {
dao.addUser(user);
System.out.println("提交事务");
} catch (Exception e) {
e.printStackTrace();
System.out.println("事务回滚");
}finally{
System.out.println("关闭链接");
}
}
@Override
public void updateUser(User user) {
dao.updateUser(user);
System.out.println("权限校验");
System.out.println("事务管理");
System.out.println("开启事务");
try {
dao.updateUser(user);
System.out.println("提交事务");
} catch (Exception e) {
e.printStackTrace();
System.out.println("事务回滚");
}finally{
System.out.println("关闭链接");
}
}
@Override
public void deleteById(int id) {
dao.deleteById(id);
}
}
测试类
package com.biyi.admintest;
import com.biyi.controller.UserController;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:springconfig.xml")
public class AdminTest {
@Autowired
private UserController userController;
public void fun1(){
userController.addUser();
System.out.println();
}
}
动态代理
package com.biyi.action;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Poxy {
public static void main(String[] args) {
Star star=new Star();
Class<? extends Star> aClass = star.getClass();
Skill dailiobj= (Skill) Proxy.newProxyInstance(aClass.getClassLoader(), aClass.getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("商家与经纪人沟通");
System.out.println("签合同");
System.out.println("给钱");
Object obj=method.invoke(star, args);
System.out.println("关闭链接");
return obj;
}
});
dailiobj.sing();
dailiobj.dance();
}
}
interface Skill{
void sing();
void dance();
}
class Star implements Skill{
public void sing(){
System.out.println("唱歌好听");
}
public void dance(){
System.out.println("跳舞");
}
}
Spring cglib代理
Star star=new Star();
Class<? extends Star> aClass = star.getClass();
Enhancer enhancer =new Enhancer();
enhancer.setClassLoader(aClass.getClassLoader());
enhancer.setInterfaces(aClass.getInterfaces());
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("商家与经纪人沟通");
System.out.println("签合同");
System.out.println("给钱")
Object obj=method.invoke(star,objects);
System.out.println("关闭链接");
return obj;
}
});
Skill dailiobj = (Skill) enhancer.create();
System.out.println(dailiobj.getClass());
dailiobj.sing();
dailiobj.dance();
}
}
interface Skill{
void sing();
void dance();
}
class Star implements Skill{
public void sing(){
System.out.println("唱歌好听");
}
public void dance(){
System.out.println("跳舞");
}
}
Spring aop
实现aop
需求实现service逻辑的业务的增强(事务的管理)
其余的代码为三层代码结构的代码
创建切面类
package com.biyi.aspect;
import org.aopalliance.intercept.Invocation;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import java.lang.reflect.Method;
@Component
public class MyAspect implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation Invocation) throws Throwable {
System.out.println("开启事务");
Method method = Invocation.getMethod();
Object obj = Invocation.proceed();
System.out.println("提交事务");
return obj;
}
}
编写aop代理类的代码之后要告诉我对谁增强,那么就用到了aop的配置
aop的配置
<?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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="com.biyi"/>
<!--配置aop,指定那些类的哪些方法需要被增强
那么这个有规则
id的值是ID的名称,
expression:表达式 1, within 粗粒度 也就是说只能定位到类上 2,excution是相对来说叫细粒度,可以定位到某个方法的
* com.biyi.service.*.*(..)其中*标示所有这句话说明在com.biyi.service包下的所有方法增强
<aop:config proxy-target-class="true">
proxy-target-class="true"jdk代理
proxy-target-class="false"。cglib代理
但是我们一般不写
-->
<aop:config >
<aop:pointcut id="point" expression="execution(* com.biyi.service.*.*(..))"/>
<aop:pointcut id="point" expression="within(com.biyi.service.*)"/><!--关于within的使用由于只能定位到类上所以后面到不能使用-->
<!--增强什么样的逻辑,也就是我们写的切面,切面类放到容器,在这里引用-->
<!--配置通知-->
<aop:advisor advice-ref="myAspect" pointcut-ref="point"/>
</aop:config>
</beans>
测试类
package com.biyi.admintest;
import com.biyi.controller.UserController;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:springconfig.xml")
public class AdminTest {
@Autowired
private UserController userController;
public void fun1(){
userController.addUser();
System.out.println();
}
}
其余的代码为三层代码结构
代码的复用性
其余的就是三层代码结构
下面的这是测试类的代码

aop的通知
在上面的情况是都执行了一遍,但是有时候只需要部分执行, 比如 在方法执行之前执行,在方法执行之后执行,有时候在方法前后进行管理,那么这种情况就需要用到通知 但是如果我们都将这种通知,写到代理对象中就会出现代码冗余,耦合性高这种情况
aop的5大通知
前置通知 后置通知 环绕通知 最终通知 异常通知
创建新的代理类
package com.biyi.aspect;
import org.springframework.stereotype.Component;
@Component
public class MySecond {
public void a(){
System.out.println("前置通知before");
}
}
配置类
前置通知
在springconfig文件里面
<?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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="com.biyi"/>
<!-- <aop:config>
<aop:pointcut id="point" expression="execution(* com.biyi.service.*.*(..))"/>
<aop:pointcut id="point" expression="within(com.biyi.service.*)"/>由于只能定位到类上所以后面到不能使用–>
<aop:advisor advice-ref="myAspect" pointcut-ref="point"/>
</aop:config>-->
<!--Spring的6大通知
前置通知(就是业务执行之前进行使用),比如权限校验
后置通知(就是业务执行之前进行使用),比如日志管理
环绕通知(就是业务执行之前后进行使用)某个方法执行的时间等
最终通知(方法执行结束之后进行使用)
异常通知就是在方法中出现之后有异常出现进行使用
引介通知
-->
<aop:config>
<!--对于service是开启事务-->
<aop:pointcut id="point1" expression="execution(* com.biyi.service.*.*(..))"/>
<!--对于dao是日志管理-->
<aop:pointcut id="point2" expression="execution(* com.biyi.dao.*.*(..))"/>
<!--使用Spring到通知进行增强-->
<aop:aspect ref="mySecond">
<aop:before method="a" pointcut-ref="point1"/>
</aop:aspect>
</aop:config>
</beans>
创建新的代理类
package com.biyi.aspect;
import org.springframework.stereotype.Component;
@Component
public class MySecond {
public void a(){
System.out.println("前置通知before");
}
}
执行结果

后置通知
配置类
<?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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="com.biyi"/>
<!-- <aop:config>
<!– <aop:pointcut id="point" expression="execution(* com.biyi.service.*.*(..))"/>–>
<aop:pointcut id="point" expression="within(com.biyi.service.*)"/><!–由于只能定位到类上所以后面到不能使用–>
<aop:advisor advice-ref="myAspect" pointcut-ref="point"/>
</aop:config>-->
<!--Spring的6大通知
前置通知(就是业务执行之前进行使用),比如权限校验
后置通知(就是业务执行之前进行使用),比如日志管理
环绕通知(就是业务执行之前后进行使用)某个方法执行的时间等
最终通知(方法执行结束之后进行使用)
异常通知就是在方法中出现之后有异常出现进行使用
引介通知
-->
<aop:config>
<!--对于service是开启事务-->
<aop:pointcut id="point1" expression="execution(* com.biyi.service.*.*(..))"/>
<!--对于dao是日志管理-->
<aop:pointcut id="point2" expression="execution(* com.biyi.dao.*.*(..))"/>
<!--使用Spring到通知进行增强-->
<aop:aspect ref="mySecond">
<aop:before method="a" pointcut-ref="point1"/>
<aop:after method="after" pointcut-ref="point2"/>
</aop:aspect>
</aop:config>
</beans>
代理类
package com.biyi.aspect;
import org.springframework.stereotype.Component;
@Component
public class MySecond {
public void a(){
System.out.println("前置通知before");
}
public void after(){
System.out.println("后置通知after");
}
}
环绕通知和异常通知
配置文件
<?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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="com.biyi"/>
<!-- <aop:config>
<!– <aop:pointcut id="point" expression="execution(* com.biyi.service.*.*(..))"/>–>
<aop:pointcut id="point" expression="within(com.biyi.service.*)"/><!–由于只能定位到类上所以后面到不能使用–>
<aop:advisor advice-ref="myAspect" pointcut-ref="point"/>
</aop:config>-->
<!--Spring的6大通知
前置通知(就是业务执行之前进行使用),比如权限校验
后置通知(就是业务执行之前进行使用),比如日志管理
环绕通知(就是业务执行之前后进行使用)某个方法执行的时间等
最终通知(方法执行结束之后进行使用)
异常通知就是在方法中出现之后有异常出现进行使用
引介通知
-->
<aop:config>
<!--对于service是开启事务-->
<aop:pointcut id="point1" expression="execution(* com.biyi.service.*.*(..))"/>
<!--对于dao是日志管理-->
<aop:pointcut id="point2" expression="execution(* com.biyi.dao.*.*(..))"/>
<!--使用Spring到通知进行增强-->
<aop:aspect ref="mySecond">
<aop:before method="a" pointcut-ref="point1"/>
<aop:after method="after" pointcut-ref="point2"/>
<aop:around method="around" pointcut-ref="point1"/>
<aop:after-returning method="afterreturning" pointcut-ref="point1"/>
<aop:after-throwing method="afterthrow" pointcut-ref="point1" throwing="e"/>
</aop:aspect>
</aop:config>
</beans>
代理类
package com.biyi.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.stereotype.Component;
@Component
public class MySecond {
public void a(){
System.out.println("前置通知before");
}
public void after(){
System.out.println("后置通知after");
}
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("方法执行前");
Object obj = joinPoint.proceed();
System.out.println("方法执行后");
return obj;
}
public void afterreturning(){
System.out.println("最终通知");
}
public void afterthrow(Exception e){
System.out.println(1/0);
}
}
package com.biyi.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.stereotype.Component;
@Component
public class MySecond {
public void a(){
System.out.println("前置通知before");
}
public void after(){
System.out.println("后置通知after");
}
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("方法执行前");
Object obj = joinPoint.proceed();
System.out.println("方法执行后");
return obj;
}
public void afterreturning(){
System.out.println("最终通知");
}
public void afterthrow(Exception e){
System.out.println("throwing");
}
}
注解通知开发
package com.biyi.aspect;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class MyThird {
@Pointcut("execution(* com.biyi.service.*.*(..))")
public void print1(){}
@Before("print1()")
public void before(){
System.out.println("这是前置通知");
}
@After("print1()")
public void after(){
System.out.println("后置通知after");
}
@Around("print1()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("方法执行前");
Object obj = joinPoint.proceed();
System.out.println("方法执行后");
return obj;
}
@AfterReturning("print1()")
public void afterreturning(){
System.out.println("最终通知");
}
@afterthrowing("print1()")
public void afterthrow(){
System.out.println("throwing");
}
}
在配置类里面添加开启aop注解驱动

<!--开启aop的驱动-->
<aop:aspectj-autoproxy/>
|