Spring框架(三)————IoC使用扩展和AOP
一.IoC使用扩展
1.多种方式实现依赖注入:
(1)设置注入:Spring通过setter访问器实现了对属性的赋值
具体代码如下:实体类Demo
public class Demo {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Demo{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
spring配置文件spring_conf.xml
<bean id="demo1" class="com.bdqn.entity.Demo">
<property name="id" value="1"/> <!--通过调用set方法-->
<property name="name" value="张三"/>
</bean>
测试类
public class Junit {
@Test
public void test1(){
ApplicationContext context=new ClassPathXmlApplicationContext("spring_conf.xml");
Demo obj1=(Demo)context.getBean("demo1");
System.out.println(obj1);
}
}
执行结果为:Demo{id=1, name=‘张三’}
注意:实体类必须有set方法
(2)构造注入:Spring通过构造方法赋值的能力
具体代码如下:实体类Demo
public class Demo {
private int id;
private String name;
public Demo() {
}
public Demo(int id, String name) {
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "Demo{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
spring配置文件spring_conf.xml
<!--通过调用构造方法-->
<bean id="demo3" class="com.bdqn.entity.Demo">
<constructor-arg><value type="int">3</value></constructor-arg>
<constructor-arg><value>tom</value></constructor-arg>
</bean>
测试类
public class Junit {
@Test
public void test1(){
ApplicationContext context=new ClassPathXmlApplicationContext("spring_conf.xml");
Demo obj1=(Demo)context.getBean("demo1");
System.out.println(obj1);
}
}
执行结果为:Demo{id=1, name=‘张三’}
注意:实体类必须有构造方法
(3)使用p命名空间实现属性注入
具体代码如下 :实体类Demo
public class Demo {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Demo{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
spring配置文件spring_conf.xml
<bean id="demo4" class="com.bdqn.entity.Demo" p:id="4" p:name="lisa"/>
测试类
public class Junit {
@Test
public void test1(){
ApplicationContext context=new ClassPathXmlApplicationContext("spring_conf.xml");
Demo obj1=(Demo)context.getBean("demo1");
System.out.println(obj1);
}
}
执行结果为:Demo{id=1, name=‘张三’}
注意:使用p命名空间改进配置,使用前要先添加p命名空间的声明
xmlns:p="http://www.springframework.org/schema/p"
2.注入不同数据类型
- 特殊字符串处理
- JavaBean
- List
- Array
- Set
- Map
- Properties
- 空字符串
- null值
具体代码如下:
实体类TestEntity
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public class TestEntity {
private String specialCharacter1; // 特殊字符值1
private String specialCharacter2; // 特殊字符值2
private User innerBean; // JavaBean类型
private List<String> list; // List类型
private String[] array; // 数组类型
private Set<String> set; // Set类型
private Map<String, String> map; // Map类型
private Properties props; // Properties类型
private String emptyValue; // 注入空字符串值
private String nullValue = "init value"; // 注入null值
public void setSpecialCharacter1(String specialCharacter1) {
this.specialCharacter1 = specialCharacter1;
}
public void setSpecialCharacter2(String specialCharacter2) {
this.specialCharacter2 = specialCharacter2;
}
public void setInnerBean(User user) {
this.innerBean = user;
}
public void setList(List<String> list) {
this.list = list;
}
public void setArray(String[] array) {
this.array = array;
}
public void setSet(Set<String> set) {
this.set = set;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public void setProps(Properties props) {
this.props = props;
}
public void setEmptyValue(String emptyValue) {
this.emptyValue = emptyValue;
}
public void setNullValue(String nullValue) {
this.nullValue = nullValue;
}
public void showValue() {
System.out.println("特殊字符1:" + this.specialCharacter1);
System.out.println("特殊字符2:" + this.specialCharacter2);
System.out.println("内部Bean:" + this.innerBean.getUsername());
System.out.println("List属性:" + this.list);
System.out.println("数组属性[0]:" + this.array[0]);
System.out.println("Set属性:" + this.set);
System.out.println("Map属性:" + this.map);
System.out.println("Properties属性:" + this.props);
System.out.println("注入空字符串:[" + this.emptyValue + "]");
System.out.println("注入null值:" + this.nullValue);
}
}
实体类User
public class User implements java.io.Serializable {
private String username; // 用户名
// getter & setter
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
spring配置文件spring_conf.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">
<bean id="entity" class="com.bdqn.entity.TestEntity">
<!--使用<![CDATA[P&G]]>标记处理xml特殊字符-->
<property name="specialCharacter1" >
<value><![CDATA[P&G]]></value>
</property>
<!--把xml特殊字符转换成实体引用-->
<property name="specialCharacter2">
<value>P&G</value>
</property>
<!--定义内部bean-->
<property name="innerBean">
<bean class="com.bdqn.entity.User">
<property name="username">
<value>lisa</value>
</property>
</bean>
</property>
<!--定义list中的元素-->
<property name="list">
<list>
<value>篮球</value>
<value>足球</value>
</list>
</property>
<!--定义数组中的元素-->
<property name="array">
<list>
<value>篮球</value>
<value>足球</value>
</list>
</property>
<!--定义set中的元素-->
<property name="set">
<set>
<value>篮球</value>
<value>足球</value>
</set>
</property>
<!--定义Map中的键/值对-->
<property name="map">
<map>
<entry>
<key>
<value>basketball</value>
</key>
<value>篮球</value>
</entry>
<entry>
<key>
<value>football</value>
</key>
<value>足球</value>
</entry>
</map>
</property>
<!--定义Propertites中的键/值对-->
<property name="props">
<props>
<prop key="basketball">篮球</prop>
<prop key="football">足球</prop>
</props>
</property>
<!--注入空字符串值-->
<property name="emptyValue">
<value></value>
</property>
<!--注入null值-->
<property name="nullValue">
<null/>
</property>
</bean>
</beans>
测试类:
@Test
public void testEntity(){
ApplicationContext context=new ClassPathXmlApplicationContext("spring_config.xml");
TestEntity entity1=(TestEntity)context.getBean("entity");
entity1.showValue();
}
执行结果:
**
3.使用注解实现IoC的配置
**
(1)使用注解定义Bean
- @Component:该注解与等效。
- @Respository:用于标注Dao类。
- @Service:用于标注业务逻辑类。
- @Controller:用于标注控制器类。
@Component是Spring提供的通用的组件注解。@Component、@Controller、@Service和@Repository功能一样,可以互换,我们使用不同注解主要为了区分被注解的类处在不同的业务层,使逻辑更加清晰。这四个注解主要是定义bean,创建bean。
注意:
它们使用方法:(1)标注在类上
(2)@Component(“name”)等于@Component(value=“user”)
(3)@Component相当于@Component(“className”)
(2)使用注解实现Bean组件装配
- @Resource :注入对象类型
- @Autowired :注入对象类型,默认按照类型注入。结合@Qualifier注解完成按名称的注入。
(3)加载注解定义的Bean
<!--context 命名空间下的component-scan 标签是扫描注解标注的类 -->
<!--base-package 属性指定需要扫描的基准包(多个用逗号隔开)-->
<context:component-scan base-package="com.bdqn.dao,com.bdqn.service"/>
</beans>
具体实现代码如下:
package com.bdqn.entity;
public class Users {
private String name;
private String sex;
private int age;
public Users() {
}
public Users(String name, String sex, int age) {
this.name = name;
this.sex = sex;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package com.bdqn.dao;
public interface UsersDao {
//通过用户名得到密码
public String getPwd(String name);
}
数据访问层UsersDaoImpl
package com.bdqn.dao.impl;
import com.bdqn.dao.UsersDao;
import org.springframework.stereotype.Repository;
@Repository("usersDao")
public class UsersDaoImpl implements UsersDao {
@Override
public String getPwd(String name) {
//忽略数据库操作
return name;
}
}
package com.bdqn.service;
public interface UsersService {
public String getPwd(String name);
}
业务逻辑层UsersServiceImpl
package com.bdqn.service.impl;
import com.bdqn.dao.UsersDao;
import com.bdqn.service.UsersService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service("usersService")
public class UsersServiceImpl implements UsersService {
@Autowired
@Qualifier("usersDao")
private UsersDao usersDao;
@Override
public String getPwd(String name) {
return usersDao.getPwd(name);
}
}
spring配置文件spring_config.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">
<context:component-scan base-package="com.bdqn.dao,com.bdqn.service"/>
</beans>
测试类:
@Test
public void testZhujie(){
ApplicationContext context=new ClassPathXmlApplicationContext("spring_config.xml");
UsersService usersService=(UsersService) context.getBean("usersService");
String pwd=usersService.getPwd("admin");
System.out.println(pwd);
}
执行结果:admin
二.AOP使用扩展
1.AspectJ 是一个面向切面的框架,它拓展了Java语言,定义了AOP语法,能够在编译期间提供代码的织入,所以它有一个专门的编译器用来生产遵守字节编码规范的Class文件。
Spring通过集成AspectJ实现以注解的方式定义切面,大大减少了配置文件的工作量。此外因为Java的反射机制无法获取方法参数名,Spring还需要利用轻量级的字节码处理框架 asm(已集成在Spring Core 模块中)处理@AspectJ中所描述的方法参数名。
2.使用注解标注切面
AspectJ支持5种类型的通知注解:
- @Before: 前置通知,在方法执行之前执行
- @After: 后置通知,在方法执行之后执行
- @AfterRunning:返回通知,在方法返回结果之后执行
- @AfterThrowing:异常通知,在方法抛出异常之后
- @Around: 环绕通知,围绕着方法执行
配置切面
- 切面必须是 IOC 中的 bean: 实际添加了 @Component 注解
- 声明是一个切面: 添加 @Aspect
- 声明通知: 即额外加入功能对应的方法!!.
注意:
- 编写切面类(把横切关注点的代码抽象到切面的类中):
- 一个一般的 Java 类
- 在其中添加要额外实现的功能.
3 使用注解定义切面来实现功能
具体代码如下:
实体类Target
package com.bdqn.aop;
public class Target {
public String show(String name) throws Exception {
System.out.println("这是目标方法...");
//处理异常的if条件
/*if (1/0==1){
throw new Exception("除数不能为0");
}*/
return "hello"+name;
}
}
增强类AdviceTarget
package com.bdqn.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import java.util.logging.Logger;
@Aspect
public class AdviceTarget {
@Before("execution(* com.bdqn.aop.*.*(..))")
//前置增强
public void before(JoinPoint point){
System.out.println("调用:"+point.getTarget()+"方法名:"+point.getSignature().getName()+
"参数为:"+ point.getArgs());
}
@After("execution(* com.bdqn.aop.*.*(..))")
//后置增强
public void after(JoinPoint point){
System.out.println("后置增强");
}
@AfterReturning(pointcut= "execution(* com.bdqn.aop.*.*(..))",returning = "value")
//后置带返回值
public void afterReturn(JoinPoint point,Object value){
System.out.println("后置带返回值:"+value);
}
@AfterThrowing(value = "execution(* com.bdqn.aop.*.*(..))",throwing = "ex")
//后置带异常
public void afterException(JoinPoint point,Exception ex){
System.out.println("后置带异常:"+ex);
}
//@Around("execution(* com.bdqn.aop.*.*(..))")
//环绕增强
public void around(ProceedingJoinPoint point){
String str=(String)point.getArgs()[0];
if (str.equals("admin")){
//有权限,可以访问目标方法
try {
String value=point.proceed().toString();
System.out.println("返回值"+value);
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}else {
System.out.println("无权限访问");
}
}
}
配置文件spring_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/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="target" class="com.bdqn.aop.Target"/>
<bean id="adviceTarget" class="com.bdqn.aop.AdviceTarget"/>
<aop:aspectj-autoproxy/>
</beans>
@Test
public void testAops() {
ApplicationContext context = new ClassPathXmlApplicationContext("spring_aop.xml");
Target target = (Target) context.getBean("target");
try {
target.show("admin");
} catch (Exception e) {
System.out.println("除数不能为0");
}
}
执行结果: