3.4 ,bean的作用域
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MfnYWCMc-1614954831564)(C:\Users\QiJian\AppData\Roaming\Typora\typora-user-images\Snipaste_2020-11-28_20-33-00.png)]
1,单例模式(spring默认机制)
只管理单一 bean 的一个共享实例,对 ID 或 ID 与 bean 定义相匹配的 bean 的所有请求都将导致 Spring 容器返回一个特定 bean 实例。
<bean id="accountService" class="com.something.DefaultAccountService" scope="singleton"/>
下面的图片展示了单例模式的工作原理:
2,原型模式
The non-singleton prototype scope of bean deployment results in the creation of a new bean instance every time a request for that specific bean is made. That is, the bean is injected into another bean or you request it through a getBean() method call on the container. As a rule, you should use the prototype scope for all stateful beans and the singleton scope for stateless beans.
Bean 部署的非单例原型范围导致每次对特定 bean 发出请求时都会创建一个新的 bean 实例。也就是说,bean 被注入到另一个 bean 中,或者您通过容器上的 getBean ()方法调用请求它。通常,您应该为所有有状态 bean 使用原型范围,为无状态 bean 使用单例范围。
<bean id="accountService" class="com.something.DefaultAccountService" scope="prototype"/>
下图说明了 Spring 的原型范围:
注意:每次从容器中get的时候,都会产生一个新的对象!
3,其余的request,session,application,这些只能在web开发中使用到!
4,bean的自动装配
环境:
Cat.class
package com.qijan.pojo; public class Cat { public void shout(){ System.out.println("miao~~~"); } }
Dog.class
package com.qijan.pojo; public class Dog { public void shout(){ System.out.println("wang~~"); } }
People.class
package com.qijan.pojo; import com.qijan.pojo.Cat; import com.qijan.pojo.Dog; public class People { private String name; private Cat cat; private Dog dog; public String getName() { return name; } public void setName(String name) { this.name = name; } public Cat getCat() { return cat; } public void setCat(Cat cat) { this.cat = cat; } public Dog getDog() { return dog; } public void setDog(Dog dog) { this.dog = dog; } @Override public String toString() { return "People{" + "name='" + name + '\'' + "\n, cat=" + cat + "\n, dog=" + dog + '}'; } }
bean.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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="cat" class="com.qijan.pojo.Cat"/> <bean id="dog" class="com.qijan.pojo.Dog"/> <!-- <bean id="people" class="com.qijan.pojo.People">--> <!-- <property name="name" value="qijian"/>--> <!-- <property name="dog" ref="dog"/>--> <!-- <property name="cat" ref="cat"/>--> <!-- </bean>--> <!-- 自动装配 byName:会自动在容器上下文查找,和自己对象set方法后面的值对应的bean id--> <bean id="people" class="com.qijan.pojo.People" autowire="byName"> <property name="name" value="qijian"/> </bean> </beans>
测试类
import com.qijan.pojo.People; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; @Test public void test1(){ ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); People people = context.getBean("people", People.class); people.getCat().shout(); people.getDog().shout(); System.out.println(people.toString()); } }
- 自动装配是Spring满足bean依赖的一种方式
- Spring会在上下文寻找,并自动给bean装配属性!;
在spring中有三种装配方式
- 在xml中显示的配置
- 在Java中显示的配置
- 隐式的自动装配bean【重要】
4.1,ByName自动装配
<bean id="cat" class="com.qijan.pojo.Cat"/> <bean id="dog" class="com.qijan.pojo.Dog"/> <!-- <bean id="people" class="com.qijan.pojo.People">--> <!-- <property name="name" value="qijian"/>--> <!-- <property name="dog" ref="dog"/>--> <!-- <property name="cat" ref="cat"/>--> <!-- </bean>--> <!-- 自动装配 byName:会自动在容器上下文查找,和自己对象set方法后面的值对应的bean id--> <bean id="people" class="com.qijan.pojo.People" autowire="byName"> <property name="name" value="qijian"/> </bean>
4.2 byType自动装配
<bean class="com.qijan.pojo.Dog"/> <bean class="com.qijan.pojo.Cat"/> <!-- 自动装配 byType: 会自动在容器上下文查找,和自己对象属性类型相同的bean 可以不用设置bean id --> <bean id="people" class="com.qijan.pojo.People" autowire="byType"> <property name="name" value="qijian"/> </bean>
小结:
- byName:需要保证bean的id的唯一,并且这个bean需要和自动注入的属性的set方法的值一致
- byType:需要保证所有的bean的class唯一,并且这个bean需要和自动注入的属性的类型一致!
4.4,使用注解实现自动装配
jdk1.5 开始支持注解,spring2.5开始支持注解
要使用注解须知:
导入约束
配置注解支持
您可以将它们注册为单独的 bean 定义,但也可以通过在基于 xml 的 Spring 配置中包含以下标记来隐式注册它们(注意包含上下文名称空间) :
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <context:annotation-config/>//注解的支持,需要添加进去。 </beans>
@Autowired
直接在属性上使用即可!也可以在set方法使用!
使用Autowired我们可以不用编写Set方法,前提是你的这个自动装配的属性在(spring)容器中存在,且符合名字byname!
@Nullable 字段标记了这个注解,说明这个字段可以为null
public @interface Autowired{ boolean required() default true; }
代码测试:
//使用在属性上
// 如果显示定义了Autowired的required属性为false,说明这个对象可以为null,否则不允许为空 // @Autowired(required = false) @Autowired private Cat cat; public People(@Nullable Cat cat) { this.cat = cat; }
//对构造函数应用@autowired 注释,如下面的例子所示:
public class People{ private String name; ... @Autowired public void People(String name){} ... }
//可以将@autowired 注释应用于传统的 setter 方法,如下面的示例所示:
public class People{ private String name; ... @Autowired public void setName(String name){ this.name = name; } }
//还可以将注释应用于具有任意名称和多个参数的方法等。
如果@Autowired自动装配的环境比较复杂,自动装配无法通过注解【@AutoWired】完成的时候,我们可以使用@Qualifier(value=“newcatName”)去配合@Autowired的使用,指定一个唯一的bean对象注入
public class People{ @Autowired @Qualifier(value="newcatname") private Cat cat; @Autowired @Qualifier(value="nawdogname") private Dog dog; ... }
注意:@Qualifier于@Autowired注解配合使用,会将默认的按bean类型装配修改为按Bean的实例名称装配,Bean的实例名称由@Qualifier注解的指定。
从 Spring Framework 4.3开始,如果目标 bean 从一开始就只定义一个构造函数,那么在这样的构造函数上就不再需要@autowired 注释了。但是,如果有多个构造函数可用,并且没有主/默认构造函数,那么至少有一个构造函数必须用@autowired 注释,以便指示容器使用哪个构造函数。有关详细信息,请参阅关于构造函数解析的讨论。
@resource功能比较强大,但是使用的较少
public class People{ @Resource(name="cat2") private Cat cat; @Resource private Dog dog; ... }
注意:
@Resource和@Autowired的区别
都是用来自动装配的,都可以放在属性字段上
@Autowired通过byName的方式实现
@Resource默认通过byname的方式实现,如果找不到名字,则通过byType实现!如果两个都找不到的情况下,就会报错!
执行的顺序不同:@Autowired
5,使用注解开发
在Spring4之后,要使用注解开发,必须要保证aop的包导入,使用注解需要导入context约束,增加注解的支持!
- bean
- 属性如何注入
//java文件
package com.qijian.pojo; import org.springframework.stereotype.Component; @Component public class User { private String name = "qijian"; @Override public String toString() { return "User{" + "name='" + name + '\'' + '}'; } }
//配置文件
<?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 https://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.qijian.pojo"/> <!-- 注解--> <context:annotation-config/> </beans>
衍生注解
@Component有几个衍生注解,我们在web开发中,会按照mvc三层架构分层!
dao【@Repository】
service【@Service】
controller【@Controller】
这四个注解功能时一样的,都是代表将莫格1类注册到Spring中
- 自动装配
@Autowired,@Qualifier(value =“XXX”),@Resource - 作用域
@Scope 例如:@Scope(“prototype”) 写在类的上面
@Component @Scope("prototype") public class People{ // @Value("qijian") private String name; //相当于<property name="name" value="qijian"> @Value("qijian")//写在此处与写在属性上面时一样的,但是如果复杂的注入时不建议使用 public void setName(String name){ this.name=name; } }
- 小结:xml与注解
- xml更加万能,适用于任何场合!维护简单方便
- 注解不是自己类使用不了,维护相对复杂!
最佳实践:
- xml用来管理bean;
- 注解只负责完成属性的注入;
- 使用过程中我们需要注意,要让注解生效,就必须开启注解的支持
<!-- 指定扫描的包,这个包下的注解会生效--> <context:component-scan base-package="com.qijian.pojo"/> <!-- 注解--> <context:annotation-config/>
注意:
使用注解开发时,UerControllerDD user = context.getBean(“uerControllerDD”,UerControllerDD.class);前面的参数(bean的名字)需要最从一定的格式不然就不能够从容器中拿到对应的bean。只需要把该类的第一个字母小写放在其中就可以了。并且如果出现下面的情况那么注入的属性的值时由注解决定的。
@Value("柒间") private String name = "qijan";
6,使用Java的方式配置Spring
qijianConfig.class
package com.qijian.config; import com.qijian.dao.User; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; //这个也会被spring容器托管,注册到容器中,因为它本身就是一个@Conponent //@Configuration代表这个是一个配置类,就和我们之前的beans.xml @Configuration @ComponentScan("com.qijian.dao") @Import(qijianConfig2.class)//把qijianConfig2配置类导入 public class qijianConfig { //注册一个bean,相当于我们之前的bean标签 // 这个方法的名字,就相当于bean标签的id属性 // 这个方法的返回值,就相当于bean标签中的class属性 @Bean public User getUser(){ return new User();//返回注入到bean的对象 } }
qijianConfig.class
package com.qijian.config; public class qijianConfig2 { }
User.class
package com.qijian.dao; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; //这里这个注解的意思就是说明这个类被spring接管了,注册到了容器中 @Component public class User { private String name ; @Override public String toString() { return "User{" + "name='" + name + '\'' + '}'; } public String getName() { return name; } @Value("qijian") public void setName(String name) { this.name = name; } }
MyTest.class
import com.qijian.config.qijianConfig; import com.qijian.dao.User; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class MyTest { @Test public void Test1(){ //如果完全使用了配置类方式去做,我们只能通过AnnotationConfig上下文来获取容器,通过配置文件获取class对象加载 ApplicationContext context = new AnnotationConfigApplicationContext(qijianConfig.class); User user = context.getBean("getUser", User.class); System.out.println(user.toString()); } }
7,代理模式
角色分析
- 抽象角色:一般会用接口或者抽象类来解决
- 真实角色:被代理的角色
- 代理角色:代理真实角色,代理真实角色后,我们一般会做一些附属操作
- 客户:访问代理对象的人
代码步骤:
- 接口
public interface Rent { public void rent(); }
- 真实角色:
public class Host implements Rent { public void rent() { System.out.println("出租房子"); } }
- 代理角色:
public class Proxy { private Host host; public Proxy(){} public Proxy(Host host){ this.host=host; } public void rent(){ seeHouse(); host.rent(); heTong(); fare(); } //看房 public void seeHouse(){ System.out.println("中介看房"); } // public void heTong(){ System.out.println("签订和同"); } //收中介费 public void fare(){ System.out.println("收中介费"); } }
- 客户段访问代理角色
public class Client { public static void main(String[] args) { //房东出租房子 Host host = new Host(); // 代理,中介帮房东出租,代理角色一般会有些附属操作! Proxy proxy = new Proxy(host); //不用面对房东直接找中介,租房就可以了 proxy.rent(); } }
代理模式的好处:
- 可以使真实角色的操作更加纯粹!不用区关注一些公共业务
- 公共业务交给代理角色!实现了业务的分工!
- 公共业务发生拓展的时候,方便集中管理!
缺点:
- 一个真实的角色就会产生一个代理的角色;代码量会翻倍~开发效率变慢
8,AOP
8.1 什么是AOP
AOP全称是Aspect Oriented Programming,及面向切面编程(也称面向方面编程),是面向对象编程(OOP)的一种补充,目前已经成为一种比较成熟的编程方式。
AOP出现的原因:在传统的业务处理代码中,通常都会进行事务处理,日志记录的操作。OOP可以通过组合或继承的方法实现代码的重用,但如果要实现某个功能(如日志的记录),相同的代码仍然会分散到各个方法中去。这样,如果想关闭某个功能,或者对其修改,就必须修改所有相关的方法。这不但参加了开发人员的工作量,而且提高了代码的出错率。为了解决这个问题,AOP的思想随之产生。AOP采取横向抽取的机制,将分散在各个方法中的代码提取出来,然后在程序编译或运行时再将这些提取出来的代码应用到需要执行的地方。这种采用横向抽取的方式,采用传统的OOP思想是无法办到的,因为OOP只能实现父子关系的纵向重用。虽然AOP是一种新的编程思想,但却不是OOP的替代品,它只是OOP的延伸和补充。
8.2 AOP在spring中的作用
在AOP的思想中,通过Aspect(切面)可以在不同类的方法中加入事务,日志,权限和异常等功能。
AOP的使用使开发人员在编写业务逻辑的时候可以专心于核心业务,而不用过多的关注其他业务逻辑的实现,这不但提高了开发的效率,而且提高了代码的可维护性。
总的来说,利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
横切关注点:跨越应用程序多个模块的方法或功能。及是与我们的业务逻辑无关,但是我们需要关注的部分就是横切关注点:如日志安全,缓存,事务等等
切面(Aspect):横切关注点被模块化的特殊对象。即它的一个类
通知(Advice):切面必须要完成的工作,即它是类的一个方法
目标(Target):被通知对象
代理(Proxy):向目标对象应用通知后创建对象
切入点(PointCut)切面通知执行的“地点”的定义
连接点(JointPoint):与切入点匹配额的执行点
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MBVCdQBf-1619604879564)(C:\Users\QiJian\Pictures\Typora\point.png)]
8.3 使用spring实现AOP
**【重点】**使用AOP,需要导入一个依赖包
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.4</version> <scope>runtime</scope> </dependency>
方式一:使用spring的API接口
导入spring-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:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd "> <!-- bean definition & AOP specific configuration --> </beans>
搭建如下:
//UserService接口 package com.qijian.service; public interface UserService { public void add(); public void delete(); public void update(); public void select(); }
UserService接口的实现类
//UserServiceImpl类 package com.qijian.service; public class UserServiceImpl implements UserService{ @Override public void add() { System.out.println("增加了一个用户"); } @Override public void delete() { System.out.println("删除了一个用户"); } @Override public void update() { System.out.println("更新了一个用户"); } @Override public void select() { System.out.println("查询了一个用户"); } }
Log类
package com.qijian.log; import org.springframework.aop.MethodBeforeAdvice; import java.lang.reflect.Method; public class Log implements MethodBeforeAdvice { //method : 要执行的目标对象的方法、 //args: 参数 // target:目标对象 //执行方法之前自行调用 @Override public void before(Method method, Object[] args, Object target) throws Throwable { System.out.println(target.getClass().getName()+"的"+method.getName()+"被执行了!"); } }
AfterLog类
package com.qijian.log; import org.springframework.aop.AfterReturningAdvice; import java.lang.reflect.Method; public class AfterLog implements AfterReturningAdvice { //执行方法后调用 @Override public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { System.out.println("执行了"+ method.getName()+"方法,返回结果为:"+returnValue); } }
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:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <!--注册bean--> <bean id="userService" class="com.qijian.service.UserServiceImpl"/> <bean id="log" class="com.qijian.log.Log"/> <bean id="afterLog" class="com.qijian.log.AfterLog"/> <!--注册bean--> <!--配置aop:需要导入aop的约束--> <aop:config> <!--1, 配置切入点 --> <!-- id:用于定义切入点的唯一标识 expression:用于指定切入点关联的切入点表达式。 expression=“execution(* ..*.*(..))”;//需要注意的是第一个*与包之间有一个空格 expression:用来匹配执行方法的连接点 第一个*表示匹配任意的方法的返回值 第一个..表示service包及其子包 第二个*表示所有类 第三个*表示所有方法 第二个..表示方法的任意参数个数 --> <aop:pointcut id="pointcut" expression="execution(* com.qijian.service.UserServiceImpl.*(..))"/> <!--执行环绕增加--> <aop:advisor advice-ref="log" pointcut-ref="pointcut"/> <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/> </aop:config> </beans>
注意:配置通知的常用属性如下
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y2rzBfyM-1619604879566)(C:\Users\QiJian\Pictures\Typora\A1CF9B5A2C39ABB632A54D68E32B98BD.png)]
父pom.xml文件
<?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>org.example</groupId> <artifactId>springaop</artifactId> <packaging>pom</packaging> <version>1.0-SNAPSHOT</version> <modules> <module>spring-09-aop</module> </modules> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.4</version> <scope>runtime</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.9.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-web --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>5.2.9.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-web --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.9.RELEASE</version> </dependency> </dependencies> </project>
子pom.xml文件
<?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"> <parent> <artifactId>springaop</artifactId> <groupId>org.example</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>spring-09-aop</artifactId> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>5.3.1</version> </dependency> <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.4</version> <scope>runtime</scope> </dependency> </dependencies> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> </project>
方式二:自定义类实现AOP【主要定义切面】
自定义类:
package com.qijian.diy; public class DiyPointCat { public void before(){ System.out.println("========方法执行前========"); } public void after(){ System.out.println("=========方法执行后========"); } }
applicationContext.xml配置
<bean id="diy" class="com.qijian.diy.DiyPointCat"/> <aop:config> <!--自定义切面--> <aop:aspect ref="diy"> <!--切入点--> <aop:pointcut id="point" expression="execution(* com.qijian.service.UserServiceImpl.*(..))"/> <!--通知--> <aop:before method="before" pointcut-ref="point"/> <aop:after method="after" pointcut-ref="point"/> </aop:aspect> </aop:config>
方式三:使用注解实现【使用注解方式实现AOP】
基于XML的声明式AspectJ实现AOP编程虽然便捷,但是要在Spring文件中配置大量的代码信息。为了解决这个问题AspectJ框架为AOP的实现提供了一套注解,用以取代spring配置文件中为实现AOP功能所配置的臃肿代码。
在方式二的环境中添加一个类:
package com.qijian.diy; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.Signature; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; //使用注解方式显现AOP @Aspect //标注这个类是一个切面e public class AnnotionPointCut { @Before("execution(* com.qijian.service.UserServiceImpl.*(..))") public void before(){ System.out.println("========方法执行前========"); } @After("execution(* com.qijian.service.UserServiceImpl.*(..))") public void after(){ System.out.println("=====方法执行后===="); } // 在环绕增强中,我们可以给定一个参数,代表我们要获取处理切入的点 @Around("execution(* com.qijian.service.UserServiceImpl.*(..))") public void around(ProceedingJoinPoint jp) throws Throwable { System.out.println("环绕前"); Signature signature = jp.getSignature();//获得签名 System.out.println("signature : " + signature); //执行方法 Object proceed = jp.proceed(); System.out.println("环绕后!"); } }
以上需要注意,注解开发需要两个依赖如下,虽然说aspectjweaver包含了aspectjrt,但是不知道为什么写代码的过程中没有aspectjrt这个依赖就是不能实现注解开发(此处有待商榷待找到原因后再来记录)。
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.6.11</version> </dependency> <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.6.11</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:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <!--注册bean--> <bean id="userService" class="com.qijian.service.UserServiceImpl"/> <bean id="log" class="com.qijian.log.Log"/> <bean id="afterLog" class="com.qijian.log.AfterLog"/> <!-- 方式三 使用注解开发--> <bean id="annotionPointCut" class="com.qijian.diy.AnnotionPointCut"/> <!-- 开启注解支持--> <aop:aspectj-autoproxy /> </beans>
测试类:
public class MyTest { @Test public void test(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserService userService = (UserService)context.getBean("userService"); userService.add(); } }
结果:
环绕前 signature : void com.qijian.service.UserService.add() ========方法执行前======== 增加了一个用户 =====方法执行后==== 环绕后!