一、Spring IOC容器初始化过程
Ioc容器是一个Map集合 (可以通过getBean()方法获取到对应key的value,value存放的是对象)。这边引用一下整体流程图片。
①自定义bean的xml文件 (比如数据库的配置)
<!--bean信息如下所示-->
<context:property-placeholder location="dbconfig.properties"/>
<bean>
<!--属性填充,value用占位符,并没有真正的赋值-->
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="driverClassName" value="${jdbc.driverclass}"/>
<property name="url" value="${jdbc.url}"/>
</bean>
②通过BeanDefinitionReader读取bean文件成为BeanDefinition对象,${}占位符并没有真正获取。
③XmlBeanDefinitionReader的实现方法
//XmlBeanDefinitionReader调用的是父类AbstractBeanDefinitionReader构造方法
public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) {
super(registry);
}
//父类AbstractBeanDefinitionReader的构造方法如下
protected AbstractBeanDefinitionReader(BeanDefinitionRegistry registry) {
//先断言registry非空
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
this.registry = registry;
// instance of判断registry是否是ResourceLoader的子类
if (this.registry instanceof ResourceLoader) {
this.resourceLoader = (ResourceLoader) this.registry;
}
else {
this.resourceLoader = new PathMatchingResourcePatternResolver();
}
// instance of判断registry是否是EnvironmentCapable的子类
if (this.registry instanceof EnvironmentCapable) {
this.environment = ((EnvironmentCapable) this.registry.getEnvironment();
}
else {
this.environment = new StandardEnvironment();
}
}
④BeanDefinition所包含的内容
下图就是beanDefinition所包含的内容。看到这些属性如果对Spring有所了解都应该知道几个,如lazyInit懒加载,在Spring中有一个@Lazy注解,用来标识其这个bean是否为懒加载的,scope属性,相应的也有@scope注解来标识这个bean其作用域,是单例还是多例,beanClass属性,在对象实例化时,会根据beanClass来创建对象、又比如autowireMode注入模型这个属性,这个属性用于记录使用怎样的注入模型,注入模型常用的有根据名称和根据类型、不注入三种注入模型等。
⑤BeanDefinition接口定义了大量的常量和方法,具体如下
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
// 常量标志一个bean的作用范围
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
// 设置父BeanDefinition,可以只对有父子关系的bean
void setParentName(@Nullable String parentName);
String getParentName();
// bean的类的全限定名
void setBeanClassName(@Nullable String beanClassName);
String getBeanClassName();
void setScope(@Nullable String scope);
String getScope();
void setLazyInit(boolean lazyInit);
boolean isLazyInit();
// 设置依赖性,被依赖的bean会优先创建
void setDependsOn(@Nullable String... dependsOn);
String[] getDependsOn();
// 是否允许自动装配
void setAutowireCandidate(boolean autowireCandidate);
boolean isAutowireCandidate();
// 设置是否主要bean
void setPrimary(boolean primary);
boolean isPrimary();
// 工厂bean和工厂方法
void setFactoryBeanName(@Nullable String factoryBeanName);
String getFactoryBeanName();
void setFactoryMethodName(@Nullable String factoryMethodName);
String getFactoryMethodName();
ConstructorArgumentValues getConstructorArgumentValues();
default boolean hasConstructorArgumentValues() {
return !getConstructorArgumentValues().isEmpty();
}
// 使用setter注入时的key-value对,都保存在这里
MutablePropertyValues getPropertyValues();
default boolean hasPropertyValues() {
return !getPropertyValues().isEmpty();
}
// @since 5.1初始化方法和销毁方法
void setInitMethodName(@Nullable String initMethodName);
String getInitMethodName();
void setDestroyMethodName(@Nullable String destroyMethodName);
String getDestroyMethodName();
// 为bean设置角色
void setRole(int role);
int getRole();
// bean的描述
void setDescription(@Nullable String description);
String getDescription();
// 返回此bean定义的可解析类型,基于bean类或其他特定元数据。
// 这通常在运行时合并bean定义上完全解决但不一定是在配置时定义实例上。
ResolvableType getResolvableType();
boolean isSingleton();
boolean isPrototype();
boolean isAbstract();
}
⑥Java类 ---> BeanDefinition类的代码
//************AbstractBeanDefinition类*********************
public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
implements BeanDefinition, Cloneable {
// 定义一些常量
public static final String SCOPE_DEFAULT = "";
public static final int AUTOWIRE_NO = AutowireCapableBeanFactory.AUTOWIRE_NO;
public static final int AUTOWIRE_BY_NAME = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;
public static final int AUTOWIRE_BY_TYPE = AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE;
// ...还有很多
// 初始化默认值
private volatile Object beanClass;
private String scope = SCOPE_DEFAULT
private boolean autowireCandidate = true;
private boolean primary = false;
// ...还有很多
// 构造器
protected AbstractBeanDefinition() {
this(null, null);
}
// 指定构造器参数和属性参数
protected AbstractBeanDefinition(@Nullable ConstructorArgumentValues cargs, @Nullable MutablePropertyValues pvs) {
this.constructorArgumentValues = cargs;
this.propertyValues = pvs;
}
// 使用深拷贝创建一个新的
protected AbstractBeanDefinition(BeanDefinition original) {
}
// 复制一个bean的定义到当前bean,通常父子bean合并时可用
public void overrideFrom(BeanDefinition other) {
}
// ...此处省略其他的方法实现
}
//*******************GenericBeanDefinition类*********************
public class GenericBeanDefinition extends AbstractBeanDefinition {
@Nullable
private String parentName;
public GenericBeanDefinition() {
super();
}
// 通过深拷贝创建一个bean
public GenericBeanDefinition(BeanDefinition original) {
super(original);
}
@Override
public void setParentName(@Nullable String parentName) {
this.parentName = parentName;
}
@Override
@Nullable
public String getParentName() {
return this.parentName;
}
@Override
public AbstractBeanDefinition cloneBeanDefinition() {
return new GenericBeanDefinition(this);
}
}
//测试
@Test
public void testGenericBeanDefinition(){
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClassName("com.ydlclass.User");
// 此处类似setter注入的描述
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.addPropertyValue("name","lily");
propertyValues.addPropertyValue("age",12);
beanDefinition.setPropertyValues(propertyValues);
}
⑦在这里Spring为我们提供了一个扩展的切口,允许我们通过实现接口BeanFactoryPostProcessor 在此处来插入我们定义的代码。后置处理器BeanFactoryPostProcessor还完成了@Bean、@Component等注解解析,这个后置处理器可以将${xxx}占位符替换为实际的字符串值。典型的例子就是:PropertyPlaceholderConfigurer,我们一般在配置数据库的dataSource时使用到的占位符的值,就是它注入进去的。
public abstract class PropertyResourceConfigurer extends PropertiesLoaderSupport
implements BeanFactoryPostProcessor, PriorityOrdered {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws
BeansException {
try {
Properties mergedProps = mergeProperties();
// Convert the merged properties, if necessary.
convertProperties(mergedProps);
// Let the subclass process the properties.
processProperties(beanFactory, mergedProps);
}
catch (IOException ex) {
throw new BeanInitializationException("Could not load properties", ex);
}
}
}
⑧然后通过BeanDefinitionRegistry将这些BeanDefinition对象注册到beanFactory容器中。
@SuppressWarnings("serial")
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
/** Map of bean definition objects, keyed by bean name */
private final Map<String, BeanDefinition> beanDefinitionMap = new
ConcurrentHashMap<String, BeanDefinition>(64);
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
// ... ...
this.beanDefinitionMap.put(beanName, beanDefinition);
// ... ...
}
}
⑨Spring IOC容器的最后说明:Spring提供IOC容器实现两种方式(两个接口):BeanFactory和ApplicationContext。
>BeanFactory:
>>IOC容器基本实现,是Spring内部的使用接口,不提供开发人员进行使用
>>加载配置文件Xml的时候不会创建对象,在获取对象的时候才去创建对象
>ApplicationContext:
>>BeanFactory接口的子接口,提供更多更强大的功能,一般由开发人员使用
>>加载配置文件Xml的时候就会把在配置文件对象进行创建
二、Spring Bean的生命周期
我们知道一般的对象生命周期是这样的:先通过new关键字将对象实例化到堆中,然后就可以使用Java对象了,不再使用对象之后通过JVM垃圾回收销毁。但是Spring Bean的生命周期不是这样,具体步骤如下所示:Bean实例化-->Bean属性赋值-->初始化-->销毁这四个阶段。
①上述是Bean本身的方法,加上IOC容器的生命周期(BeanPostProcessor 一系列接口)
② InstantiationAwareBeanPostProcessor 是继承了 BeanPostProcessor
//InstantiationAwareBeanPostProcessor接口的定义
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
@Nullable
default 0bject postProcessBeforeInstantiation(Class<?> beanClass,String beanName)
throws BeansException {
return null;
}
default 0bject postProcessBeforeInstantiation(Class<?> beanClass,String beanName)
throws BeansException {
return true;
}
@Nullable
default 0bject postProcessBeforeInstantiation(Class<?> beanClass,String beanName)
throws BeansException {
return null;
}
@Deprecated
@Nullable
default 0bject postProcessBeforeInstantiation(Class<?> beanClass,String beanName)
throws BeansException {
return pvs;
}
}
//BeanPostProcessor接口的定义
public interface BeanPostProcessor {
@Nullable
default 0bject postProcessBeforeInitialization(Object bean,String beanName) throws
BeansException {
return bean;
}
@Nullable
default 0bject postProcessAfterInitialization(Object bean,String beanName) throws
BeansException {
return bean;
}
}
③InstantiationAwareBeanPostProcessor接口中的方法介绍
方法 | 描述 |
---|---|
postProcessBeforeInitialization | BeanPostProcessor接口中的方法,在Bean的自定义初始化方法之前执行 |
postProcessAfterInitialization | BeanPostProcessor接口中的方法,在Bean的自定义初始化方法之后执行 |
postProcessBeforeInstantiation | 自身方法,是最先执行的方法,它在目标对象实例化之前调用,该方法的返回值类型是Object,我们可以返回任何类型的值。由于这个时候目标对象还未实例化,所以这个返回值可以用来代替原本该生成的目标对象的实例(比如代理对象)。如果该方法的返回值代替原本该生成的目标对象,后续只有postProcessAfterInitialization方法会调用,其它方法不再调用;否则按照 按照正常的流程走 |
postProcessAfterInstantiation | 在目标对象实例化之后调用,这个时候对象已经被实例化,但是该实例的属性还未被设置,都是null。因为它的返回值是决定要不要调用postProcessPropertyValues方法的其中一个因素(因为还有一个因素是mbd.getDependencyCheck());如果该方法返回false,并且不需要check,那么postProcessPropertyValues就会被忽略不执行;如果返回true,postProcessPropertyValues就会被执行 |
postProcessPropertyValues | 对属性值进行修改,如果postProcessAfterInstantiation方法返回false,该方法可能不会被调用。可以在该方法内对属性值进行修改 |
④Bean级生命周期的方法之一(Aware类型的接口):让我们能够拿到 Spring 容器中的一些资源。
因为 Aware 方法都是执行在初始化方法之前,所以可以在初始化方法中放心大胆的使用 Aware 接口获取的资源,这也是我们自定义扩展 Spring 的常用方式。
方法 | 描述 |
---|---|
BeanNameAware | 需要实现setBeanName()方法,这个方法只是简单的返回我们当前的beanName, 知道自己在spring容器里的名字 |
BeanClasLoaderAware | 获取Bean的类装载器 |
BeanFactoryAware | 获取Bean的工厂 |
EnviromentAware | 可以获得application.properties的配置文件配置的属性值 |
EmbeddedValueResolverAware | 基于Spring解析获取properties文件的单个属性值 |
ApplicationContextAware/ResourceLoaderAware | ApplicationContextAware接口会自动的将程序上下文加入 |
⑤Bean级生命周期方法之二(生命周期类型接口):自己实现的有初始化和销毁两个生命周期阶段。spring初始化bean的时候,如果bean实现了InitializingBean接口,会自动调用afterPropertiesSet方法,在bean被销毁的时候如果实现了DisposableBean接口会自动回调destroy方法后然后再销毁。
方法 | 描述 |
---|---|
InitializingBean | 对应生命周期的初始化阶段。InitializingBean接口为bean提供了初始化方法的方式,它只包括afterPropertiesSet方法,凡是继承该接口的类,在初始化bean的时候都会执行该方法 |
DisposableBean | 类似InitializingBean,对应生命周期销毁阶段。允许在容器销毁该bean的时候获得一次回调 |
⑥Spring Bean生命周期流程图
三、代码演示
①UserBean类
//UserBean类的定义、继承接口InitializingBean/BeanNameAware/DisposableBean
@Component
public class UserBean implements InitializingBean, BeanNameAware, DisposableBean, ApplicationContextAware {
private int id;//id属性
private String name;//name属性
//UserBean构造器
public UserBean(int id, String name) {
this.id = id;
this.name = name;
System.out.println("2. 调用构造函数");
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
System.out.println("5. 属性注入 id");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
System.out.println("5. 属性注入 name");
}
//实现接口BeanNameAware的setBeanName方法
@Override
public void setBeanName(String name) {
System.out.println("6. 调用 BeanNameAware.setBeanName() 方法");
}
//实现方法setApplicationContext
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws
BeansException {
UserBean userBean = (UserBean) applicationContext.getBean("userBean");
System.out.println(userBean);
System.out.println("7. 调用 BeanNameAware.setBeanName() 方法");
}
//实现方法afterPropertiesSet()
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("9. 调用 InitializingBean.afterPropertiesSet() 方法");
}
//初始化方法
public void myInit() {
System.out.println("10. 调用 init-method 方法");
}
//实现DisposableBean的destroy销毁方法
@Override
public void destroy() throws Exception {
System.out.println("12. 调用 DisposableBean.destroy() 方法");
}
//销毁方法
public void myDestroy() {
System.out.println("13. 调用 destroy-method 方法");
}
//toString()方法打印对象
@Override
public String toString() {
return "UserBean{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
②InstantiationAwareBeanPostProcessor 接口实现类
@Component
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if ("userBean".equals(beanName)) {
System.out.println("1. 调用 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation() 方法");
}
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if ("userBean".equals(beanName)) {
UserBean userBean = (UserBean) bean;
System.out.println("3. 调用 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation() 方法");
System.out.println(userBean);
}
return true;
}
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
if ("userBean".equals(beanName)) {
System.out.println("4. 调用 InstantiationAwareBeanPostProcessor.postProcessProperties() 方法");
}
return null;
}
}
③BeanPostProcessor 接口实现类
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if ("userBean".equals(beanName)) {
System.out.println("8. 调用 BeanPostProcessor.postProcessBeforeInitialization() 方法");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if ("userBean".equals(beanName)) {
System.out.println("11. 调用 BeanPostProcessor.postProcessAfterInitialization() 方法");
}
return bean;
}
}
④BeanFactoryPostProcessor 接口实现类
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("0. 调用 BeanFactoryPostProcessor.postProcessBeanFactory() 方法");
}
}
⑤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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
">
<bean class="com.riemann.test.MyInstantiationAwareBeanPostProcessor" />
<bean id="userBean" class="com.riemann.test.UserBean" init-method="myInit" destroy-method="myDestroy">
<!-- 构造函数注入 -->
<constructor-arg index="0" type="int">
<value>1</value>
</constructor-arg>
<constructor-arg index="1" type="java.lang.String">
<value>Spring Bean生命周期</value>
</constructor-arg>
<!-- setter方法注入 -->
<property name="id" value="2"/>
<property name="name" value="zlw"/>
</bean>
<bean class="com.riemann.test.MyBeanPostProcessor" />
<bean class="com.riemann.test.MyBeanFactoryPostProcessor" />
</beans>
⑥测试类
//测试类
public class BeanLifeCycleTest {
public static void main(String[] args) {
ApplicationContext applicationContext = new
ClassPathXmlApplicationContext("classpath:applicationContext.xml");
UserBean user = (UserBean) applicationContext.getBean("userBean");
((AbstractApplicationContext) applicationContext).close();
}
}
⑦打印结果
0. 调用 BeanFactoryPostProcessor.postProcessBeanFactory()方法
1. 调用InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()方法
2. 调用构造函数
3. 调用InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()方法UserBean{id=1, name='Spring Bean生命周期'}
4. 调用InstantiationAwareBeanPostProcessor.postProcessProperties()方法
5. 属性注入id
5. 属性注入name
6. 调用BeanNameAware. setBeanName()方法
UserBean{id=2, name= 'riemann '}
7. 调用 BeanNameAware. setBeanName()方法
8. 调用 BeanPostProcessor.postProcessBeforeInitialization()方法
9. 调用InitializingBean.afterPropertiesSet()方法
10.调用init-method 方法
11,调用BeanPostProcessor.postProcessAfterInitialization()方法
UserBean{id=2,name= 'riemann ' }
12.调用 DisposableBean.destroy()方法
13.调用destroy-method 方法
四、Spring Aop
Spring Aop是面向切片编程(方面),利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各个部分之间的耦合度降低 提高程序的可重复性,同时提高了开发效率,AOP底层使用的是动态代理。
①Spring Aop的操作术语:
②切入点表达式:
//举例切入点表达式1,对com.atguigu.dao.BookDao类里面的add进行增强
//*表示所有权限修饰符,对返回值类型进行省略(void),对类路径BookDao下的add进行增强,(..)表示两个形参
execution(*com.atguigu.dao.BookDao.add(..))
//举例切入点表达式2,对com.atguigu.dao.BookDao类里面的所有方法进行增强
execution(*com.atguigu.dao.BookDao.*(..))
//举例切入点表达式3,对com.atguigu.dao包里面所有的类,类里面的所有方法进行增强
execution(*com.atguigu.dao.*.*(..))
③AspectJ注解对AOP的操作步骤一(创建类和增强类):
//User类
package com.atguigu.spring5.aopanno;
public class User{
public void add(){ System.out.println("add......"); }
}
//增强类
package com.atguigu.spring5.aopanno;
public class UserProxy{
//前置通知
public void before(){ System.out.println("before....."); }
}
④进行通知配置
<bean>
<!--1.开启注解扫描-->
<context:component-scan base-package="com.atguigu.spring5.aopano"></context:component-scan>
<!--4.开启AspectJ生成代理对象-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
⑤增强类上添加@AspectJ注解,并在类上加注解@Component使其能够扫描到
package com.atguigu.spring5.aopanno;
import org.springframework.stereotype.Component;
//2.被增强的类注解
@Component
public class User{
public void add(){ System.out.println("add......"); }
}
package com.atguigu.spring5.aopanno;
import org.springframework.stereotype.Component;
//2.增强的类注解
@Component
//3.生成代理对象注解
@AspectJ
public class UserProxy{
//前置通知
public void before(){ System.out.println("before....."); }
}
⑥在代理类的通知方法上面添加通知类型注解,使用切入点表达式配置
package com.atguigu.spring5.aopanno;
import org.springframework.stereotype.Component;
//2.增强的类注解
@Component
//3.生成代理对象注解
@AspectJ
public class UserProxy{
//前置通知
//@Before表示前置通知,写切入点表达式
@Before(value="execution(*com.atguigu.spring5.aopanno.User.add(..))")
public void before(){ System.out.println("before....."); }
}
⑦各个通知举例说明
package com.atguigu.spring5.aopanno;
import org.springframework.stereotype.Component;
@Component
@AspectJ
public class UserProxy{
//1.前置通知
//@Before表示前置通知,写切入点表达式
@Before(value="execution(*com.atguigu.spring5.aopanno.User.add(..))")
public void before(){ System.out.println("before....."); }
//2.最终通知,有没有异常都执行
//@After表示后置通知
@After(value="execution(*com.atguigu.spring5.aopanno.User.add(..))")
public void after(){ System.out.println("after......"); }
//3.环绕通知
//@Around表示环绕通知
@Around(value="execution(*com.atguigu.spring5.aopanno.User.add(..))")
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
System.out.println("环绕之前......");
//被增强的方法执行
proceedingJoinPoint.proceed();
System.out.println("环绕之后......");
}
//4.异常通知
//@AfterThrowing表示异常通知
@AfterThrowing(value="execution(*com.atguigu.spring5.aopanno.User.add(..))")
public void afterThrowing(){ System.out.println("afterThrowing......"); }
//5.后置通知(返回通知),有异常不执行
//@AfterReturning表示异常通知
@AfterReturning(value="execution(*com.atguigu.spring5.aopanno.User.add(..))")
public void afterReturning(){ System.out.println("afterReturning......"); }
}
⑧相同切入点的提取
package com.atguigu.spring5.aopanno;
import org.springframework.stereotype.Component;
@Component
@AspectJ
public class UserProxy{
//相同切入点抽取
@Pointcut(value="execution(*com.atguigu.spring5.aopanno.User.add(..))")
public void pointdemo(){ }
@Before(value="pointdemo()")
public void before(){ System.out.println("before....."); }
@After(value="pointdemo()")
public void after(){ System.out.println("after......"); }
@Around(value="pointdemo()")
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
System.out.println("环绕之前......");
//被增强的方法执行
proceedingJoinPoint.proceed();
System.out.println("环绕之后......");
}
@AfterThrowing(value="pointdemo()")
public void afterThrowing(){ System.out.println("afterThrowing......"); }
@AfterReturning(value="pointdemo()")
public void afterReturning(){ System.out.println("afterReturning......"); }
}
⑨多个增强类对同一个方法进行增强,设置优先级
//在增强类上面添加一个注解@Order(数字类型的值),数字类型值越小优先级越高
package com.atguigu.spring5.aopanno;
import org.springframework.stereotype.Component;
@Component
@AspectJ
@Order(1)
public class UserProxy{
//前置通知
//@Before表示前置通知,写切入点表达式
@Before(value="execution(*com.atguigu.spring5.aopanno.User.add(..))")
public void before(){ System.out.println("user before....."); }
}
package com.atguigu.spring5.aopanno;
import org.springframework.stereotype.Component;
@Component
@AspectJ
@Order(3)
public class PersonProxy{
//前置通知
//@Before表示前置通知,写切入点表达式
@Before(value="execution(*com.atguigu.spring5.aopanno.User.add(..))")
public void before(){ System.out.println("person before....."); }
}
//@Order(1)>@Order(3)的优先级,先执行UserPorxy后执行PersonPorxy
⑩AOP的AspectJ配置文件或者完全注解开发
<bean>
<!--创建对象-->
<bean id="user" class="com.atguigu.spring5.aopanno.User"></bean>
<bean id="userProxy" class="com.atguigu.spring5.aopanno.UserProxy"></bean>
<!--配置aop增强-->
<aop:config >
<!--切入点-->
<aop:pointcut id="p"expression="execution(*com.atguigu.spring5.aopanno.User.add(..))">
<!--配置切面-->
<aop:aspect ref="userProxy">
<!--增强作用在具体的方法上-->
<aop:before method="before" pointcut-ref="p"/>
</aop:aspect>
</aop:pointcut>
</aop:config>
</beans>
package com.atguigu.spring5.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@ComponentScan(basePackage = {"com.atguigu"})
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class ConfigAop{
}
最后
本文有参考很多大佬的文章,也有引用图片和内容,仅供于参考学习,如有错误还望指点。