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&amp;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();
    }

执行结果:
Spring框架(三)————IoC使用扩展和AOP

**

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");
        }

    }

执行结果:
Spring框架(三)————IoC使用扩展和AOP