Spring框架 — IOC和AOP使用扩展
1.多种方式实现依赖注入
-
构造函数注入
<bean id="accountService" class="com.accp.service.impl.accountServiceImpl"> <constructor-arg name="name" value="张三"></constructor-arg> <constructor-arg name="age" value="18"></constructor-arg> <constructor-arg name="birthday" ref="now"></constructor-arg> </bean>
标签的属性:
-
type:用于指定要注入的数据的数据类型,该数据类型也是构造函数中的某个或某些参数
-
index:用于指定要注入的数据给构造函数中指定索引位置的参数赋值,索引位置从0开始
-
name:用于指定给构造函数中指定名称的参数赋值
-
value:用于提供基本类型和String类型的数据
-
ref:用于指定其他bean类型的数据。它指的是在spring的IOC核心容器出现过的bean对象
-
-
使用set方法注入
<bean id="accountService" class="com.accp.service.impl.accountServiceImpl"> <property name="name" value="李四"></property> <property name="age" value="18"></property> <property name="birthday" ref="now"></property> </bean>
标签的属性:
-
name:用于指定注入时所调用的set方法名称
-
value:用于提供基本类型和String类型的数据
-
ref:用于指定其他bean类型的数据。它指的是在spring的IOC核心容器出现过的bean对象
-
-
复杂类型注入
<bean id="accountService" class="com.accp.service.impl.accountServiceImpl"> <!--注入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> <!--注入map--> <property name="map"> <map> <entry key="a" value="王五"></entry> <entry key="b" value="赵六"></entry> <entry key="c" value="钱七"></entry> </map> </property> <!--注入properties--> <property name="properties"> <props> <prop key="a">王五</prop> <prop key="b">赵六</prop> <prop key="c">钱七</prop> </props> </property> </bean>
2.使用注解实现IoC配置
-
在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" 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"> <!--告知spring在创建容器时需要扫描的包,配置所需要的标签不是在beans约束中, 而是一个名称为context名称空间和约束中--> <context:component-scan base-package="com.accp"></context:component-scan> </beans>
2.使用注解定义Bean
-
@Component:,value用于指定bean的id,他的默认名称是当前类名,且首字母小写
-
@Controller:一般用于表现层
-
@Service:一般用于业务层
-
@Repository:一般用在持久层
3.使用注解实现Bean组件装配
3.1.用于注入数据的
-
@Autowired:作用:自动按照类型注入。只要容器中有唯一的一个bean对象类型和要注入的变量类型匹配,就可以注入成功
@Autowired private accountDao accountDao;
-
@Qualifier(“Str”):作用:在按照类中注入的基础之上再按照名称注入,它在给类成员注入时不能单独使用(和Autowired组合在一起),但是在给方法参数注入时可以使用
@Autowired @Qualifier("accountDao") private accountDao accountDao;
-
@Resource(name = “Str”):作用:直接按照bean的id注入,可以独立使用
属性:value用于指定bean的id@Resource(name = "accountDao") private accountDao accountDao;
-
@value:作用:用于注入基本数据类型和string类型数据
属性:value用于指定数据的值,它可以使用spring中的SpEl(spring的EL表达式)
SpEl写法:${表达式}@Value("${jdbc.driver}") private String driver;
3.2.用于改变作用范围
-
@Scope:作用:用于指定bean的作用范围
@Scope("singleton") public class accountServiceImpl{}
3.3.和生命周期相关的
-
@PostConstruct:用于指定初始化方法
@PostConstruct public void init(){ System.out.println("初始化"); }
-
@PreDestroy:用于指定销毁方法
@PreDestroy public void destroy(){ System.out.println("销毁"); }
3.4.spring中的新注解
-
@Configuration:指定当前类是一个配置类
细节:当配置类作为AnnotationConfigApplicationContext对象创建的参数时该注解可以不写
@Configuration public class SpringConfiguration {}
-
@ComponentScan:通过注解指定spring在创建容器时要扫描的包
使用此注解相当于在xml中配置了:<context:component-scan base-package=“com.accp”/>
@Configuration @ComponentScan(basePackages = "com.accp") public class SpringConfiguration {}
-
@PropertySource:用于指定PropertySource文件的位置属性:
value指定文件的名称和路径,classPath指的是当前文件的类路径
@Configuration @ComponentScan(basePackages = "com.accp") @PropertySource("classpath:jdbc.properties") public class SpringConfiguration {}
-
@Bean:用于把当前方法的返回值作为bean对象存入IOC容器中
属性:name用于指定bean的id,默认值是当前方法的名称
@Bean(name = "dataSource") public DataSource createDataSource() {}
-
@Import(Class):用于导入其他配置类
4.使用注解标注AOP切面
-
@Aspect :表示当前类是一个切面类
@Aspect public class Logger {}
-
@Pointcut:
@Pointcut("execution(* com.accp.service.impl.*.*(..))") private void pt1(){}
-
@Before:前置通知
@Before("pt1()") public void prLogger(){ System.out.println("前置prLogger日志开始工作"); }
-
@AfterReturning:后置通知
@AfterReturning("pt1()") public void afterReturnPrLogger(){ System.out.println("后置afterReturnPrLogger日志开始工作"); }
-
@AfterThrowing:异常通知
@AfterThrowing("pt1()") public void afterThrowingPrLogger(){ System.out.println("异常afterThrowingPrLogger日志开始工作") }
-
@After:异常通知
@After("pt1()") public void afterPrLogger(){ System.out.println("最终afterPrLogger日志开始工作"); }
-
@Around:环绕通知
@Around("pt1()") public Object aroundLogger(ProceedingJoinPoint pjp){ Object rtValue; try { Object[] args=pjp.getArgs(); System.out.println("前置aroundLogger日志开始工作"); //proceed()此方法相当于明确调用切入点方法。 rtValue=pjp.proceed(args); System.out.println("后置aroundLogger日志开始工作"); return rtValue; } catch (Throwable e) { System.out.println("异常aroundLogger日志开始工作"); throw new RuntimeException(e); }finally { System.out.println("最终aroundLogger日志开始工作"); } }