spring:想了解IoC以及AoP一篇文章就足够了

准备工作

新建一个java project即可,学spring一个java项目足够了,后期需要什么jar包,导包就可以了
工程结构如下,导入以下几个jar包即可,本篇博客只是快速讲解ioc以及aop的入门知识,具体的每一个后续会逐个讲解
在这里插入图片描述

为什么会诞生Spring

最主要的几点如下:

  • 1、使用spring可以降低代码间的耦合度
  • 2、使用spring可以解决循环依赖问题
  • 3、我们以前的service实现类中,充斥着各种try,catch以及事务相关的代码,大部分代码是冗余的,但又是不能不写的,spring帮助我们关注具体的业务开发

ioc

什么是ioc

控制反转(Inversion of Control,缩写为IoC),可以用来减低计算机代码之间的耦合度。接下来我们看几个具体的例子,ioc容器中存储bean,我们通过配置bean,让ioc容器帮助我们创建实例,然后我们通过依赖注入,将ioc帮助我们创建的实例,注入到我们所需要的位置。

没有ioc之前

在这里插入图片描述
那么有意思的来了,假如我HelloworldDao的实现类改变了,那我必须修改我们的Service实现类,但是我们要满足一个基本的原则,即对扩展开放,对修改关闭,那么显然,上述是不符合的。

怎么配置bean

在这里插入图片描述

有了ioc之后

在这里插入图片描述
property标签,是通过调用类的setter方法。如果类中没有对应属性的setter方法,就会报错。这里值得注意的是属性是由setter方法决定的,然而变量则是在类中直接定义的。属性变量不能混为一谈。
内部bean,顾名思义,在内部使用的bean,可以保证安全性。上述xml配置文件可以修改为

<bean class="serviceImpl.HelloWorldServiceImpl" id="helloWorldService">
   		<property name="helloWorldDao">
   				<bean class="daoImpl.HelloWorldDaoImpl"/>
   		</property>
	</bean>

我们就没必要给内部bean配置id了,因为id就是给这个bean起的类似于唯一编号的东西,就像java中每个成员变量一样,名称不能重复,那么我们在使用匿名对象的时候我们是不会用一个成员变量来接收的。什么意思呐?参考下列代码:

//Class A
public class A{
	private B b;
	private A(){

	}
	public A(B b){
		this.b = b;
	}
}
//Class B
public class B{
	private int value;
	private B(){
	}
	public B(int value){
		this.value = value
	}
}
//Main函数
A a = new A(new B(2));
//看到这里就明白了,new B(2)就是个匿名对象,匿名对象只为它一个人服务

同样的内部bean也只为外部bean服务。
只需要在xml文档中简单地进行配置,就可以让ioc容器帮助我们创建一个对象,我们使用注解便可以注入进去。准确地来说使用了依赖注入(DI),接下来让我们细致的深入了解ioc。那么我们实际上如果dao的实现类发生改变,我并不需要去修改具体的service实现类,只需简单地修改bean的配置就好了,由此得出spring可以帮助我们降低代码的耦合度
而且注意了,只有某个类被ioc容器管理,我们可以明显的看到左上角有个小小的s
在这里插入图片描述

bean的实例化方式

bean的实例化方式一共有4种,目前讲解最为常见的构造器实例化,采用的是无参数构造器
在这里插入图片描述
如果你没有无参数构造器,就会报错
在这里插入图片描述

bean的属性注入方式

有参构造器注入

这种方式不能够解决循环依赖问题

什么是循环依赖

在这里插入图片描述
很明显,构造A对象,首先要有B对象,构造B对象又要有A对象,就这样无休止下去,禁止套娃

尝试使用构造器注入解决循环依赖

整体结构如下
在这里插入图片描述

public class A {
	private B b;
	public A(B b) {
		this.b = b;
		System.out.println("A构造成功");
	}
}
public class B {
	private A a;
	public B(A a) {
		this.a = a;
		System.out.println("B构造成功");
	}
}

applicationContext.xml

<bean class="test.B" id="b">
		<constructor-arg name="a" ref="a"/>
	</bean>
	<bean class="test.A" id="a">
		<constructor-arg name="b" ref="b"/>
	</bean>

很明显,我们只要能在控制台得到**构造成功,就证明我们解决了循环依赖问题
为什么我们执行main方法也能出现下面的错误?这里简单解释一下,因为这里并不是懒加载,程序开始执行时会直接把所有资源一次性加载。在这里插入图片描述
错误信息

Error creating bean with name 'b': Requested bean is currently in creation:
 Is there an unresolvable circular reference?

setter注入

只有类中有set方法,就可以通过property进行注入,值得注意的是,引用类型使用ref,简单类型使用value,集合类型使用对应的标签。而且对于这一规则构造器注入以及setter注入是通用的。

setter解决循环依赖

整体结构如下
在这里插入图片描述
xml文件

<bean class="test.B" id="b">
		<property name="a" ref="a"></property>
	</bean>
	<bean class="test.A" id="a">
		<property name="b" ref="b"></property>
	</bean>

在这里插入图片描述
A,B构造成功,解决了循环依赖问题,下面讲解给bean注入值的三种方式。

ref

在这里插入图片描述

value

新建一个类,结构如下

package entity;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@ToString
@Getter
@Setter
public class User {
	private long id;
	private List<String> list;
}

applicationContext.xml

<bean class="entity.User" id="user">
		<property name="id" value="10"/>
	</bean>

测试
在这里插入图片描述

对应集合类型标签

修改上述applicationContext.xml

	<bean class="entity.User" id="user">
		<property name="id" value="10"/>
		<property name="list">
			<list>//对应集合类型的标签
				<value>test1</value>//同样的简单类型使用value
				<value>test2</value>
				<null/>//注意设置为空比较特殊
			</list>
		</property>
	</bean>

其余的就集合类型不再展示了,下面给出官方给出的文档,里面有具体的使用方法

<bean id="moreComplexObject" class="example.ComplexObject">
    <!-- results in a setAdminEmails(java.util.Properties) call -->
    <property name="adminEmails">
        <props>
            <prop key="administrator">administrator@example.org</prop>
            <prop key="support">support@example.org</prop>
            <prop key="development">development@example.org</prop>
        </props>
    </property>
    <!-- results in a setSomeList(java.util.List) call -->
    <property name="someList">
        <list>
            <value>a list element followed by a reference</value>
            <ref bean="myDataSource" />
        </list>
    </property>
    <!-- results in a setSomeMap(java.util.Map) call -->
    <property name="someMap">
        <map>
            <entry key="an entry" value="just some string"/>
            <entry key ="a ref" value-ref="myDataSource"/>
        </map>
    </property>
    <!-- results in a setSomeSet(java.util.Set) call -->
    <property name="someSet">
        <set>
            <value>just some string</value>
            <ref bean="myDataSource" />
        </set>
    </property>
</bean>

测试
在这里插入图片描述

P命名空间

p命名空间不太常用,因为不直观
上述的

<bean class="test.B" id="b">
		<property name="a" ref="a"></property>
	</bean>
	<bean class="test.A" id="a">
		<property name="b" ref="b"></property>
	</bean>

使用p命名空间即

<bean class="test.B" id="b" p:a-ref="a"/>
	<bean class="test.A" id="a" p:b-ref="b"/>

获取bean的常用三种方式

上述我们直接使用了di注解,autowired,那么加入我们不使用注解,我们该怎么获取bean?

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 http://www.springframework.org/schema/beans/spring-beans.xsd">
   	<bean class="serviceImpl.HelloWorldServiceImpl" id="helloWorldService">
   		<property name="helloWorldDao">
   				<bean class="daoImpl.HelloWorldDaoImpl"/>
   		</property>
	</bean>
</beans>

beanFactory

什么是beanFactory

BeanFactory是Spring最古老的接口,表示Spring IoC容器- -生产bean对象的工厂,负责配置,创建和管理bean被Spring IoC容器管理的对象称之为bean。是延迟加载

使用beanFactory获取Bean

下面列举最常见的三种

通过id值去找到bean
@Test
	void main() {
		Resource resource =  new ClassPathResource("applicationContext.xml");
		BeanFactory beanFactory = new XmlBeanFactory(resource);
		//通过bean的id值,去找到bean(不推荐)
		HelloWorldService hws = (HelloWorldService)beanFactory.getBean("helloWorldService");
		hws.hello();
	}

为什么不推荐使用这种?
获取bean以后需要强制转化

通过类的字节码去找到bean
@Test
	void main() {
		Resource resource =  new ClassPathResource("applicationContext.xml");
		BeanFactory beanFactory = new XmlBeanFactory(resource);
		//通过bean的字节码,去找到bean(不推荐)
		HelloWorldService hws = beanFactory.getBean(HelloWorldService.class);
		hws.hello();
	}

优点:不用强制转化了
缺点:容易出现bean注入歧义性问题
下面来演示一下歧义性问题(修改applicationContext.xml)

	<bean class="serviceImpl.HelloWorldServiceImpl" id="helloWorldService">
   		<property name="helloWorldDao">
   				<bean class="daoImpl.HelloWorldDaoImpl"/>
   		</property>
	</bean>
	<bean class="serviceImpl.HelloWorldServiceImpl" id="helloWorldService1">
   		<property name="helloWorldDao">
   				<bean class="daoImpl.HelloWorldDaoImpl"/>
   		</property>
	</bean>

我们可以看到,对于上述配置文件,两个bean的class是一致的
再次执行main()方法,错误信息如下

org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'service.HelloWorldService' available: expected single matching bean but found 2: helloWorldService,helloWorldService1
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1199)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveBean(DefaultListableBeanFactory.java:422)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:352)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:345)
	at controller.MyTest.main(MyTest.java:18)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:515)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:115)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:171)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:167)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:114)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:59)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:105)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:95)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:71)
	at java.util.ArrayList.forEach(ArrayList.java:1249)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:110)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:95)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:71)
	at java.util.ArrayList.forEach(ArrayList.java:1249)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:110)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:95)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:71)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:220)
	at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:188)
	at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:202)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:181)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:128)
	at org.eclipse.jdt.internal.junit5.runner.JUnit5TestReference.run(JUnit5TestReference.java:89)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)


我们提取最重要的
NoUniqueBeanDefinitionException: No qualifying bean of type ‘service.HelloWorldService’ available: expected single matching bean but found 2
大概意思就是我找到两个bean,我不知道你要使用哪一个,这就是歧义性问题

通过id值以及class去找到bean
@Test
	void main() {
		Resource resource =  new ClassPathResource("applicationContext.xml");
		BeanFactory beanFactory = new XmlBeanFactory(resource);
		//通过id值以及class去找到bean(推荐)
		HelloWorldService hws = beanFactory.getBean("helloWorldService",HelloWorldService.class);
		hws.hello();
	}

通过这种方式就可以解决注入时候的歧义性问题

applicationContext

什么是applicationContext

在这里插入图片描述
我们可以看到applicationContext是一个BeanFactory的子接口,我们使用其实现类ClassPathXmlApplicationContext

使用applicationContext获取Bean

跟BeanFactory一样,有三种,这里就不再一一演示了。

@Test
	void main2() {
		ApplicationContext atx = new ClassPathXmlApplicationContext("applicationContext.xml");
		HelloWorldService hws = (HelloWorldService)atx.getBean("helloWorldService");
		HelloWorldService hws1 =atx.getBean(HelloWorldService.class);
		HelloWorldService hws2 = atx.getBean("helloWorldService", HelloWorldService.class);
	}

beanFactory以及applicationContext对比

修改service实现类

public class HelloWorldServiceImpl implements HelloWorldService {

	private HelloWorldDao helloWorldDao; 
	
	public void setHelloWorldDao(HelloWorldDao helloWorldDao) {
		this.helloWorldDao = helloWorldDao;
	}

	public HelloWorldServiceImpl() {//用来判断是否创建出该对象
		System.out.println("我被实例化了");
	}
	
	@Override
	public void hello() {
		helloWorldDao.hello();
	}

}

beanFactory


	@Test
	void main() {
		Resource resource =  new ClassPathResource("applicationContext.xml");
		BeanFactory beanFactory = new XmlBeanFactory(resource);
		//通过bean的字节码,去找到bean(不推荐)
		//HelloWorldService hws = beanFactory.getBean("helloWorldService",HelloWorldService.class);
	}

结果
在这里插入图片描述

applicationContext

@Test
	void main2() {
		ApplicationContext atx = new ClassPathXmlApplicationContext("applicationContext.xml");
		
	}

结果
在这里插入图片描述
发现我们获取bean,但是bean已经创建了,这就是没有延迟初始化。

aop

准备工作

在这里插入图片描述
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 
	http://www.springframework.org/schema/beans/spring-beans.xsd">
   	<bean class="serviceImpl.UserServiceImpl" id="userService">
   		<property name="userDao">
   			<bean class="daoImpl.UserDaoImpl" id="userDao"/>
   		</property>
   	</bean>
	
</beans>

测试能否跑通
在这里插入图片描述

基础知识

代理模式

静态代理

引入静态代理类
在这里插入图片描述

public class StaticProxy implements UserService{
	private UserService userService;
	
	public void setUserService(UserService userService) {
		this.userService = userService;
	}
	
	public void begin() {
		System.out.println("开启事务");
	}
	public void commit() {
		System.out.println("提交事务");
	}
	public void rollback() {
		System.out.println("回滚事务");
	}
	@Override
	public void addUser() {
		begin();
		try {
			userService.addUser();
			commit();
		} catch (Exception e) {
			rollback();
		}
	}
	
}

UserServiceImpl

public class UserServiceImpl implements UserService {

	private UserDao userDao; 
	
	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}
	
	@Override
	public void addUser() {
		userDao.addUser();
	}

}

applicationContxt.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 
	http://www.springframework.org/schema/beans/spring-beans.xsd">
	<bean class="transaction.StaticProxy" id="staticProxy">
		<property name="userService" ref="userService"/>
	</bean>
   	<bean class="serviceImpl.UserServiceImpl" id="userService">
   		<property name="userDao">
   			<bean class="daoImpl.UserDaoImpl" id="userDao"/>
   		</property>
   	</bean>
	
</beans>

测试
在这里插入图片描述
可以看到实例的实际类型为StaticProxy

静态代理面临的问题

优点:可以看到我们具体业务(UserServiceImpl)中没有大量的事务相关代码,以及tryCatch,看起来相当清爽
缺点
1、我们可以看到,静态代理直接实现一个接口,如果接口里面增加或者删除方法,那么我的代理类也需要做相应操作
2、我们可以看到,在静态代理类中有实际的业务实现类对象,也就是说,我们需要为每一个具体的业务实现类,写静态代理类,任务量大。

jdk动态代理

public class JdkProxy implements InvocationHandler{

	private Object target;
	private StaticProxy staticProxy;

	public void setStaticProxy(StaticProxy staticProxy) {
		this.staticProxy = staticProxy;
	}

	public void setTarget(Object target) {
		this.target = target;
	}
	
	public  Object getInstance() {
		return Proxy.newProxyInstance(
				target.getClass().getClassLoader(), 
				target.getClass().getInterfaces(),
				this);
	}
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object result = null;
		staticProxy.begin();
		try {
			result = method.invoke(target, args);
			staticProxy.commit();
		} catch (Exception e) {
			staticProxy.rollback();
		}
		return result;
	}

}

applicationContxt.xm配置

<?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 
	http://www.springframework.org/schema/beans/spring-beans.xsd">
	<bean class="transaction.JdkProxy" id="jdkProxy">
		<property name="staticProxy" ref="staticProxy"/>
		<property name="target" ref="userService"/>
	</bean>
	<bean class="transaction.StaticProxy" id="staticProxy">
		<property name="userService" ref="userService"/>
	</bean>
   	<bean class="serviceImpl.UserServiceImpl" id="userService">
   		<property name="userDao">
   			<bean class="daoImpl.UserDaoImpl" id="userDao"/>
   		</property>
   	</bean>
	
</beans>

测试:
在这里插入图片描述
我们可以看到已经使用jdk动态代理了

CGlib动态代理

public class CglibProxy implements InvocationHandler{

	private Object target;
	private StaticProxy staticProxy;

	public void setStaticProxy(StaticProxy staticProxy) {
		this.staticProxy = staticProxy;
	}

	public void setTarget(Object target) {
		this.target = target;
	}
	
	public  Object getInstance() {
		return Enhancer.create(target.getClass(), this);
	}
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object result = null;
		staticProxy.begin();
		try {
			result = method.invoke(target, args);
			staticProxy.commit();
		} catch (Exception e) {
			staticProxy.rollback();
		}
		return result;
	}

}

applicationContxt.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 
	http://www.springframework.org/schema/beans/spring-beans.xsd">
	<bean class="transaction.CglibProxy" id="cglibProxy">
		<property name="staticProxy" ref="staticProxy"/>
		<property name="target" ref="userService"/>
	</bean>
	<bean class="transaction.StaticProxy" id="staticProxy">
		<property name="userService" ref="userService"/>
	</bean>
   	<bean class="serviceImpl.UserServiceImpl" id="userService">
   		<property name="userDao">
   			<bean class="daoImpl.UserDaoImpl" id="userDao"/>
   		</property>
   	</bean>
	
</beans>

测试
在这里插入图片描述

什么是aop

aop(面向切面变编程)原理其实就是动态代理,只不过我们发现,我们使用动态代理,会把真实对象的所有方法做增强。使用aop可以对某一个方法做增强

有aop之后

修改各个类
在这里插入图片描述
applicationContxt.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-4.3.xsd">
	<bean class="serviceImpl.UserServiceImpl" id="userService">
		<property name="userDao">
			<bean class="daoImpl.UserDaoImpl"/>
		</property>
	</bean>
	<bean class="transaction.StaticProxy" id="staticProxy"/>
	
	<aop:config>
		<aop:aspect ref="staticProxy"><!-- what -->
			<aop:pointcut expression="execution(* serviceImpl.UserServiceImpl.addUser(..))" id="prf"/> <!-- where -->
			<aop:before method="begin" pointcut-ref="prf"/><!-- when -->
			<aop:after-returning method="commit" pointcut-ref="prf"/>
			<aop:after-throwing method="rollback" pointcut-ref="prf"/>
		</aop:aspect>
	</aop:config>
</beans>

对于上述我们只对addUser()进行了增强
结果
在这里插入图片描述
从上述真实类型我们可以得到使用了jdk动态代理
现在使用updateUser()看是否增强
在这里插入图片描述
我们可以看到updateUser()这个方法并未被增强,这也就解决了我们开头的问题,aop可以解决只对某一个方法进行增强。

execution表达式的书写

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值