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: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
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
</beans>
注解开发
Bean的实现
1、 配置扫描哪些包下的注解
<?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
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--指定注解扫描包-->
<context:component-scan base-package="com.study"/>
<!--开启注解的支持-->
<context:annotation-config></context:annotation-config>
</beans>
2、在指定包下编写类,增加注解
@Component("user")
// 相当于配置文件中 <bean id="user" class="当前注解的类"/>
public class User {
public String name = "张三";
}
3、测试
@Test
public void test(){
ApplicationContext applicationContext =new ClassPathXmlApplicationContext("beans.xml");
User user = applicationContext.getBean("user",User.class);
System.out.println(user.name);
属性注入
1、可以不用提供set方法,直接在直接名上添加@value("值")
// 相当于配置文件中 <bean id="user" class="当前注解的类"/>
@Component("user")
public class User {
@Value("张三")
// 相当于配置文件中 <property name="name" value="张三"/>
public String name;
}
2、如果提供了set方法,在set方法上添加@value("值");
@Component("user")
public class User {
public String name;
@Value("张三")
public void setName(String name) {
this.name = name;
}
}
衍生注解
@Component三个衍生注解
为了更好的进行分层,Spring可以使用其它三个注解,功能一样,目前使用哪一个功能都一样。
@Controller:web层(控制层)
@Service:service层(服务层)
@Repository:dao层(数据访问层)
@Component //将这个类标注为Spring的一个组件,放到容器中!
public class Dog {
public String name = "dog";
}
作用域
@scope
- singleton:默认的,Spring会采用单例模式创建这个对象。关闭工厂 ,所有的对象都会销毁。
- prototype:多例模式。关闭工厂 ,所有的对象不会销毁。内部的垃圾回收机制会回收
@Controller("user")
@Scope("prototype")
public class User {
@Value("张三")
public String name;
}
基于Java类进行配置
@Configuration //代表这是一个配置类
@Import(MyConfig2.class) //导入合并其他配置类,类似于配置文件中的inculde标签
public class MyConfig {
@Bean //通过方法注册一个bean,这里的返回值就Bean的类型,方法名就是bean的id!
public Dog dog(){
return new Dog();
}
}
AOP
AOP(Aspect Oriented Programming)意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。
通知类型 | 连接点 | 实现接口 |
---|---|---|
前置通知 | 在方法执行前执行 | org.spirngframework.aop.MethodBeforeAdvice |
后置通知 | 在方法执行后执行 | org.springframework.aop.AfterReturningAdvice |
环绕通知 | 在方法执行前后都执行 | org.aopalliance.intercept.MethodInterceptor |
异常抛出通知 | 在方法抛出异常后执行 | org.springframework.aop.ThrowsAdvice |
引介通知 | 在目标类中添加一些新的方法和属性 | org.springframework.aop.IntroductionInterceptor |
使用Spring实现Aop
导入依赖
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>
第一种实现方式:
1、编写接口
package com.sutdy.service;
public interface UserService {
public void add();
public void delete();
public void update();
public void select();
}
2、编写接口实现类
package com.study.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("查询了一个用户");
}
}
3、编写增强类
前置增强:
package com.study.log;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
//方法执行前执行该类
public class BeforeLog implements MethodBeforeAdvice {
//method:要执行的目标方法
//objects:参数
//o:目标对象
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println(o.getClass().getName()+"的"+method.getName()+"被执行了");
}
}
后置增强:
package com.study.log;
import org.springframework.aop.AfterReturningAdvice;
import java.lang.reflect.Method;
//方法执行后执行该类
public class AfterLog implements AfterReturningAdvice {
//returnValue 返回值
//method被调用的方法
//args 被调用的方法的对象的参数
//target 被调用的目标对象
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("执行了"+method.getName()+"方法,返回结果为:"+returnValue);
}
}
4、编写配置文件:
<?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 id="userService" class="com.study.service.UserServiceImpl"/>
<bean id="beforeLog" class="com.study.log.BeforeLog"/>
<bean id="afterLog" class="com.study.log.AfterLog"/>
<!--aop的实现方式一-->
<!--配置aop-->
<aop:config>
<!--切入点 execution:要执行的位置:修饰符 返回值 方法名 参数-->
<aop:pointcut id="pointcut" expression="execution(* com.study.service.UserServiceImpl.*(..))"/>
<!--执行环绕曾加-->
<aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
</aop:config>
<aop:aspectj-autoproxy/>
</beans>
5、编写测试代码:
import com.study.service.UserService;
import com.study.service.UserServiceImpl;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationConText.xml");
UserService userService = context.getBean("userService", UserService.class);
userService.select();
}
}
执行结果:
第二种实现方式
自定义类来实现Aop
1、编写一个切入类
package com.study.diy;
public class AnnotationPointCut {
@Before("execution(* com.kuang.service.*.*(..))")
public void before(){
System.out.println("=========方法执行前=======");
}
@After("execution(* com.kuang.service.*.*(..))")
public void after(){
System.out.println("=========方法执行后=======");
}
2、编写配置文件
<?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 id="userService" class="com.study.service.UserServiceImpl"/>
<bean id="beforeLog" class="com.study.log.BeforeLog"/>
<bean id="afterLog" class="com.study.log.AfterLog"/>
<!--aop的实现方式二-->
<bean id="diy" class="com.study.diy.DiyPointcut"/>
<aop:config>
<!--自定义切面 ref:要引用的类-->
<aop:aspect ref="diy">
<!--切入点-->
<aop:pointcut id="point" expression="execution(* com.study.service.UserServiceImpl.*(..))"/>
<!--通知-->
<aop:before method="before" pointcut-ref="point"/>
<aop:after method="after" pointcut-ref="point"/>
</aop:aspect>
</aop:config>
<aop:aspectj-autoproxy/>
</beans>
3.测试
第三种实现方式
使用注解实现
1、编写一个注解实现的增强类
package com.study.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 //标注这个类是一个切面
public class AnnotationPointCut {
@Before("execution(* com.kuang.service.*.*(..))")
public void before(){
System.out.println("=========方法执行前=======");
}
@After("execution(* com.kuang.service.*.*(..))")
public void after(){
System.out.println("=========方法执行后=======");
}
//在环绕增强中,我们可以给定一个参数,代表我们要获取的切入点
@Around("execution(* com.kuang.service.*.*(..))")
public void around(ProceedingJoinPoint point) throws Throwable {
System.out.println("环绕前");
//Signature signature = point.getSignature();//获得签名(类的信息)
//System.out.println("signature"+signature);
//执行方法
Object proceed = point.proceed();
System.out.println("环绕后");
//System.out.println(proceed);
}
}
2、在Spring配置文件中,注册bean,并增加支持注解的配置
<!--第三种方式:注解实现-->
<bean id="annotationPointcut" class="com.study.config.AnnotationPointcut"/>
<aop:aspectj-autoproxy/>
3、测试