Spring注入&AOP
注入
Maven里面注入Spring
创建最基本的Maven项目,进行依赖注入:
<?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>com.ifueen</groupId>
<artifactId>spring-day02</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!--Spring的核心包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<!--Context包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<!--aop的包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<!--切面的一个包(织入)-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.8</version>
</dependency>
<!-- Spring的测试包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.2.5.RELEASE</version>
<!--scope:范围,只能在test包中使用-->
<!--<scope>test</scope>-->
</dependency>
<!--junit的测试支持-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/test/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
</project>
通过构造方法注入参数
<?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 id="mybean" class="com.ifueen._02constructor.MyBean">
<!-- 通过索引配置-->
<!--<constructor-arg index="0" value="罗素"/>
<constructor-arg index="1" value="3"/>-->
<!-- 通过name配置 -->
<!--<constructor-arg name="age" value="30"/>
<constructor-arg name="name" value="爱伦坡"/>-->
<!-- 通过类型进行配置-->
<!--<constructor-arg type="java.lang.String" value="狄更斯"/>
<constructor-arg type="java.lang.Integer" value="45"/>-->
<!-- 直接根据参数顺序进行配置,注意!参数顺序一定要相对应-->
<constructor-arg value="萨特"/>
<constructor-arg value="30"/>
</bean>
</beans>
集合&数组&其他属性的注入
<?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 id="otherBean" class="com.ifueen._03rest.OtherBean"/>
<bean id="mybean" class="com.ifueen._03rest.MyBean">
<!-- 一般简单的属性 -->
<property name="id" value="1"/>
<property name="name" value="山泥若"/>
<property name="sex" value="true"/>
<property name="salary" value="797979"/>
<!-- 数组 -->
<property name="arrays">
<array>
<value>爱伦坡</value>
<value>伏尔泰</value>
<value>罗素</value>
</array>
</property>
<!-- List集合 -->
<property name="list">
<list>
<value>娄烨</value>
<value>王家卫</value>
<value>李安</value>
</list>
</property>
<!-- set集合 -->
<property name="set">
<set>
<value>诺兰</value>
<value>昆汀</value>
<value>斯皮尔伯格</value>
</set>
</property>
<!-- List集合OtherBean-->
<property name="otherBeanList">
<list>
<!-- 内部Bean -->
<bean class="com.ifueen._03rest.OtherBean"/>
<bean class="com.ifueen._03rest.OtherBean"/>
<!-- 外部引用 -->
<ref bean="otherBean"/>
<ref bean="otherBean"/>
</list>
</property>
<!-- Set集合OtherBean-->
<property name="otherBeanSet">
<list>
<!-- 内部Bean -->
<bean class="com.ifueen._03rest.OtherBean"/>
<bean class="com.ifueen._03rest.OtherBean"/>
<!-- 外部引用 -->
<ref bean="otherBean"/>
<ref bean="otherBean"/>
</list>
</property>
<!-- 简写方式 -->
<property name="props1">
<value>
drivenClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///jpa
username=root
password=123456
</value>
</property>
<!-- 标准写法 -->
<property name="props2">
<props>
<prop key="drivenClassName">com.mysql.jdbc.Driver</prop>
<prop key="url">jdbc:mysql:///hello</prop>
<prop key="username">root</prop>
<prop key="password">123456</prop>
</props>
</property>
<!-- Map集合 -->
<property name="hashMap">
<map>
<entry key="电影" value="2001太空漫步"/>
<entry key="导演" value="库布里克"/>
</map>
</property>
</bean>
</beans>
使用全注解
使用全注解的方式和之前SpringMVC的使用方式一模一样
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.ifueen._04auto"/>
</beans>
只需要将扫描包路径配置好,然后写三层架构即可
AOP(面向切面编程)
概述
定义:面向切面编程(面向方面编程)
咱们的编程语言从原始机器语言 到过程语言 再到面向对象,从始至终的目的就是为了让代码再加灵活,再加容易让人理解,构建代码更加简单。
AOP的使用只存在于一些特定的场合(具有横切逻辑的应用场合),横切逻辑这个解释可能比较抽象,咱们说得再具体一点,AOP可以用于事务管理,日志管理,性能监测等地方
面试题:Spring是如何实现AOP?
Spring是使用代理模式来实现AOP的
代理模式分两种:静态代理和动态代理
静态代理太过笨重,一般不太使用
动态代理
Spring提供了两种方案:JDK和CGLTB
如果目标对象使用了接口就让JDK来进行代理
如果目标对象没有使用接口就让CGLTB来进行代理
使用XML配置实现AOP
首先定义自定义的事务类(伪事务类)
package com.ifueen._05xmlaop;
import org.aspectj.lang.ProceedingJoinPoint;
/**
* 自己准备的一个事务
*/
public class TxManager {
public void begin(){
System.out.println("开启事务");
}
public void commit(){
System.out.println("提交事务");
}
public void rollback(Throwable e){
System.out.println("回滚事务,异常的原因为"+e.getMessage());
}
public void close(){
System.out.println("关闭资源");
}
public void around(ProceedingJoinPoint point){
/*System.out.println(point.getArgs()); //参数
System.out.println(point.getSignature()); //获取方法的签名
System.out.println(point.getTarget().getClass());//真实目标对象
System.out.println(point.getThis().getClass()); //代理对象*/
try {
//开启事务
begin();
//这里执行我们自己的代码
point.proceed();
//提交事务
commit();
} catch (Throwable throwable) {
//回滚
rollback(throwable);
throwable.printStackTrace();
}finally {
//关闭
close();
}
}
}
然后进行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.xsd">
<bean id="myBeanService" class="com.ifueen._05xmlaop.service.impl.MyBeanServiceImpl"></bean>
<bean id="txManager" class="com.ifueen._05xmlaop.TxManager"></bean>
<!-- 配置AOP -->
<aop:config>
<!--
id:切点的名称
execution是一个表达式,去执行方法
*:代表任意返回值
com.ifueen._05xmlaop.service:对应的包
I*Service:对应的类
*:所有的方法
(..):方法里面任意参数
-->
<aop:pointcut id="pointcut" expression="execution(* com.ifueen._05xmlaop.service.I*Service.*(..))"/>
<aop:aspect ref="txManager">
<!-- 前置通知 -->
<!--<aop:before method="begin" pointcut-ref="pointcut"></aop:before>-->
<!-- 后置通知 -->
<!--<aop:after-returning method="commit" pointcut-ref="pointcut"></aop:after-returning>-->
<!-- 异常通知,如果要抓取异常的话需要在这里也要设置 -->
<!--<aop:after-throwing method="rollback" pointcut-ref="pointcut" throwing="e"></aop:after-throwing>-->
<!-- 最终通知 -->
<!--<aop:after method="close" pointcut-ref="pointcut"></aop:after>-->
<!-- 环绕通知 里面可以自定义-->
<aop:around method="around" pointcut-ref="pointcut"></aop:around>
</aop:aspect>
</aop:config>
</beans>
使用注解配置AOP
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"
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
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 扫描包路径 -->
<context:component-scan base-package="com.ifueen._06annoaop"></context:component-scan>
<!-- 支持AOP注解 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
自定义的事务类
package com.ifueen._06annoaop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
/**
* 注解实现的事务
*/
@Component
@Aspect //AOP的类注解
public class TxManager {
//设置切点
@Pointcut("execution(* com.ifueen._06annoaop.service.I*Service.*(..))")
public void pointcut(){}
//前置通知
/*@Before("pointcut()")*/
public void begin(){
System.out.println("开启事务");
}
//后置通知
/*@AfterReturning("pointcut()")*/
public void commit(){
System.out.println("提交事务");
}
//异常通知
/*@AfterThrowing(pointcut = "pointcut()",throwing = "e")*/
public void rollback(Throwable e){
System.out.println("回滚事务,异常的原因为"+e.getMessage());
}
//最终通知
/*@After("pointcut()")*/
public void close(){
System.out.println("关闭资源");
}
//如果要使用环绕通知,需关闭前面的注解,不然可能引起冲突
@Around("pointcut()")
public Object around(ProceedingJoinPoint point){
Object object = null;
try {
//开启事务
begin();
//这里执行我们自己的代码
object = point.proceed();
//提交事务
commit();
} catch (Throwable throwable) {
//回滚
rollback(throwable);
throwable.printStackTrace();
}finally {
//关闭
close();
}
return object;
}
}