web44Spring笔记二

本文介绍Spring框架中使用注解进行配置的方法及AOP的应用。涵盖了导入必要的jar包、开启注解扫描、使用@Component等注解进行依赖注入,以及通过AOP实现事务管理等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 使用注解进行配置

首先肯定是导入jar包,除了第一天的四个以外,还需要导入aop的jar包

1.1 导入约束

可以从docs\spring-framework-reference\html文件夹下找到xsd-configuration.html文件进行导入,是在40.2.8那个位置。

<?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 http://www.springframework.org/schema/context/spring-context.xsd">
1.2 开启使用注解代理配置文件
<!-- 指定扫面com.dlj.bean包下的所有注解 -->
<context:component-scan base-package="com.dlj.entity"></context:component-scan>
1.3在类中使用注解完成配置
@Component( value="user")
// <bean name="user" class="...">
public class User {
	private String name;
	private Integer age;
	private Car car;
}

现在的注解除了@Component,还有@Service,@Controller,@Repository,分别是用于service层、web层、还有dao层

1.4 常用的注解

@Scope注解指定对象的作用范围,是单例还是多例

@Scope(value="prototype")
1.4.1 值类型注入

如果要给类中的某一个字段赋值,通过注解有两种方法,一种是把注解放到字段上面,还有一种是放到set方法上面,如下:

@Value(value = "tr")
	private String name;

这种事通过反射进行赋值,破坏了封装性
或者是下面:

@Value(value = "tr")
	public void setName(String name) {
		this.name = name;
	}

这种通过set方法进行赋值,是比较推荐使用的。

1.4.2 引用类型注入

这样一个场景,比如有一个car对象,user对象里面有一个属性car类型是Car类型,这个时候用注解,首先先对Car使用注解,@Component,然后再对User对象中的car属性,使用@Autowired注解,这个注解是自动装配。
在这里插入图片描述
在这里插入图片描述
但是这种方式有一个问题,如果有多个类型一致的对象,将无法选择具体注入哪一个对象。可以再使用@Qualifier()注解,该注解告诉spring容器自动装配哪个名称的对象。
还有一种方式是使用@Resource注解

@Resource(name = "car")
	private Car car;

这种更推荐
@PostConstruct 指定对象被创建后执行的方法,相当于init-method属性,@PreDestory 对象销毁之前执行的方法,相当于destory-method

2 AOP

2.1 Spring和Junit4整合

首先是导包,4+2+aop+test.

//帮我们创建容器
@RunWith(SpringJUnit4ClassRunner.class)
// 指定创建容器时,使用哪个配置文件
@ContextConfiguration("classpath:applicationContext.xml")
public class Demo {
	// 将名为user的对象注入到u变量中
	@Resource(name = "user")
	private User u;

	@Test
	public void fun1() {

		System.out.println(u);
	}
}

使用这种方式,我们就可以不用创建容器。

2.2 spring中的aop

在这里插入图片描述
spring实现aop的原理,包括动态代理,cglib代理
动态代理的局限性:被代理对象必须要实现接口,才能产生代理对象,如果没有接口将不能使用动态代理技术
cglib代理:第三方代理技术,cglib代理可以对任何类生成代理,代理的原理是对目标对象进行继承代理,如果目标对象被final修饰,那么该类无法被cglib代理。使用顺序,优先使用动态代理,没有实现接口,则使用cglib代理。下面是两个示例代码:

public class UserServiceProxyFactory implements InvocationHandler {
	private UserService us;

	public UserServiceProxyFactory(UserService us) {
		super();
		this.us = us;
	}

	public UserService getUserServiceProxy() {
		// 生成动态代理
		UserService usProxy = (UserService) Proxy.newProxyInstance(UserServiceProxyFactory.class.getClassLoader(),
				UserServiceImpl.class.getInterfaces(), this);
		return usProxy;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		// TODO Auto-generated method stub
		System.out.println("打开事务");

		Object invoke = method.invoke(us, args);
		System.out.println("关闭事务!");
		return invoke;
	}

}
public class UserServiceProxyFactory2 implements MethodInterceptor {
	private UserService us;

	public UserService getUserServiceProxy() {
		// 生成动态代理
		Enhancer en = new Enhancer();// 帮我们生成代理对象
		en.setSuperclass(UserServiceImpl.class);// 设置对谁进行代理
		en.setCallback(this);// 代理要做什么
		return (UserService) en.create();// 创建代理对象
	}

	@Override
	public Object intercept(Object proxyobj, Method method, Object[] arg, MethodProxy methodProxy) throws Throwable {
		// TODO Auto-generated method stub
		// 打开事务
		System.out.println("打开事务");
		// 调用原有方法
		Object returnValue = methodProxy.invokeSuper(proxyobj, arg);
		// 提交事务
		System.out.println("提交事务");
		return null;
	}

}
public class Demo {
	@Test
	public void fun2() {
		UserService us = new UserServiceImpl();
		// UserServiceProxyFactory2 factory = new UserServiceProxyFactory2();
		UserServiceProxyFactory2 factory = new UserServiceProxyFactory2();
		UserService usProxy = factory.getUserServiceProxy();
		usProxy.update();
	}

	public void fun1() {
		UserService us = new UserServiceImpl();
		UserServiceProxyFactory factory = new UserServiceProxyFactory(us);
		UserService usProxy = factory.getUserServiceProxy();
		usProxy.update();
	}
}
2.2.1 aop中的名词
  • Joinpoint(连接点):目标对象中所有可以增强的方法(比如上面的save方法)
  • Pointcut(切入点):目标对象中已经增强的方法
  • Advice(通知/增强):进行增强的代码
  • Target(目标对象):被代理对象
  • Waving(织入):将通知应用到切入点的过程
  • Proxy(代理):将通知织入到目标对象之后,形成代理对象
  • aspect(切面):切入点+t通知
2.3 aop演示
2.3.1导包:4+2,然后是spring的aop包和第三方的aop包。

在这里插入图片描述
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar和com.springsource.org.aopalliance-1.0.0.jar
导包以后,接着导入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.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- bean definitions here -->

</beans>
2.3.2 准备好目标对象和通知
public class MyAdvice {
	// 前置通知,目标方法运行之前调用
	// 后置通知,目标方法运行之后调用(如果出现异常都会调用)
	// 环绕通知,在目标方法之前和之后都调用
	// 异常拦截通知,如果出现异常就会调用
	// 后置通知无论时候出现异常,都会调用(无论是否出现异常都会调用)
	// -----------------------------------------------------------
	// 前置通知
	public void before() {
		System.out.println("这是前置通知!");
	}

	// 后置通知
	public void afterReturning() {
		System.out.println("这是后置通知,如果出现异常就不会调用");
	}

	// 环绕通知
	public Object around(ProceedingJoinPoint pjp) throws Throwable {
		System.out.println("这是环绕通知!之前的部分");
		Object proceed = pjp.proceed();// 调用目标方法
		System.out.println("这是环绕通知之后的部分");
		return proceed;
	}

	// 异常通知
	public void afterException() {
		System.out.println("出事啦!出现异常啦!");
	}

	// 后置通知
	public void after() {
		System.out.println("后置通知不出现异常也会调用!");
	}
}
2.3.3 配置进行织入,将通知织入目标对象中
<?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"> 

<!-- 1.配置目标对象 -->
 <bean name="userService" class="com.dlj.service.UserServiceImpl"></bean>
<!--2配置通知对象 -->
<bean name="myAdvice" class="com.dlj.e_annotationaop.MyAdvice"></bean>
<!-- 开启使用注解完成织入 -->

<!-- 3配置将通知织入目标对象 -->
<aop:config>
<!-- 配置切入点
public void com.dlj.service.UserServiceImpl.save()
 void com.dlj.service.UserServiceImpl.save()
 * com.dlj.service.UserServiceImpl.save()
 * com.dlj.service.UserServiceImpl.*     //为这个类下面的所有方法都配置切入点,但是是空参
 *  com.dlj.service.UserServiceImpl.*(..) 
  * com.dlj.service.*ServiceImpl.*(..) //service包下所有以ServiceImpl结尾的
  * com.dlj.service..*ServiceImpl.*(..) //不仅找service包下,同时还有他的子包 -->


<aop:pointcut expression="execution(* com.dlj.service.*ServiceImpl.*(..) )" id="pc"/>
<aop:aspect ref="myAdvice">
	<!-- 指定名为before的方法作为前置通知 -->
	<aop:before method="before" pointcut-ref="pc"/>
	<!-- 后置 -->
	<aop:after-returning method="afterReturning" pointcut-ref="pc"/>
	<!-- 环绕 -->
	<aop:around method="around"  pointcut-ref="pc"/>
	<!-- 异常 -->
	<aop:after-throwing method="afterException" pointcut-ref="pc"/>
	<!-- 后置 -->
	<aop:after method="after" pointcut-ref="pc"/>
</aop:aspect>
</aop:config> 
</beans>

测试代码如下:

public class Demo {
	// 将名为user的对象注入到u变量中
	@Resource(name = "userService")
	private UserService us;

	@Test
	public void fun1() {

		us.save();
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Master_Yoda

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值