本文最后更新于 2023-07-23,文章内容可能已经过时,请注意内容的辨别。

ioc和aop扩展

构造注入

必须提供带参的构造函数

而且配置文件的标签也是不一样的

public interface IUserDao {
    public  void add(User User);
}
public class UserDao implements IUserDao {
    @Override
    public void add(User User) {

        System.out.println("加了一个用户对象");
    }
}
public interface IUserservice {

    public void addUser(User User);

}
public class UserServices implements IUserservice{
    private UserDao dao;
    private String s1;
    private String s2;
    private int i;

    @Override
    public void addUser(User User) {
        dao.add(User);
    }

    public UserServices(UserDao dao, String s1, String s2, int i) {
        this.dao = dao;
        this.s1 = s1;
        this.s2 = s2;
        this.i = i;
    }

    public UserServices() {
    }
}
public class User implements java.io.Serializable {
	private Integer id; // 用户ID
	private String username; // 用户名
	private String password; // 密码
	private String email; // 电子邮件

	/* getter & setter */
	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

}
public class HelloSpringTest {

  @Test
    public  void demo(){
    ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    IUserservice service = (IUserservice) ctx.getBean("userService");
    User user = new User();
    user.setId(1);
    user.setUsername("test");
    user.setPassword("123456");
    user.setEmail("test@xxx.com");
    service.addUser(user);
  }

}
<?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="helloSpring" class="demo.HelloSpring">
        <property name="who">
            <value>Spring</value>
        </property>
    </bean>
    <bean id="userDao" class="dao.impl.UserDao">

    </bean>
    <bean id="userService" class="service.UserServices" >
        <constructor-arg>
        <ref bean="userDao"/>
    </constructor-arg>
        <constructor-arg index="1">
            <value >123</value>
        </constructor-arg>
        <constructor-arg index="3" type="int">
            <value >123</value>
        </constructor-arg>
        <constructor-arg index="2">
            <value >123</value>
        </constructor-arg>
    </bean>
    <bean id="loggerUntil" class="aop.LoggerUntil"/>
    <aop:config>
        <aop:pointcut id="pointcut"  expression="execution(  public void addUser(pojo.User))"/>
        <aop:aspect ref="loggerUntil">
            <aop:before method="before" pointcut-ref="pointcut"/>
            <aop:after-returning method="afterReturning" pointcut-ref="pointcut" returning="result"/>
        </aop:aspect>
    </aop:config>
   <!-- <aop:aspectj-autoproxy proxy-target-class="true"/>-->
</beans>
<constructor-arg index="1" type="int">
    参数位置和参数类型

与设值注入进行对比

设值注入

通过setter访问器实现

灵活性好,但setter方法数量较多

时效性差

通过无参构造实例化

构造注入

通过构造方法实现

灵活性差,仅靠重载限制太多

时效性好

通过匹配的构造方法实例化,但建议保留无参构造

p命名空间

特点

使用属性而不是子元素的形式配置Bean的属性,从而简化了配置代码

用法

使用前要先要在Spring配置文件中引入p命名空间

xmlns:p="http://www.springframework.org/schema/p"

对于直接量(基本数据类型、字符串)属性:p:属性名="属性值" 对于引用Bean的属性:p:属性名-ref="Bean的id"

<bean id="user" class="pojo.User" p:email="1020222@qq.com" p:id="1" p:password="123" p:username="张三">
</bean>

注入不同数据类型

类型方式
引用Bean使用标签实现
注意bean属性和 local 属性的区别
使用内部Bean(其他地方都没法使用)
注入集合类型的属性分别使用、、、标签实现
注入null 和空字符串值使用注入null 值
使用注入空字符串值
注入直接量使用标签实现
注意特殊字符的处理
<?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-3.2.xsd">
	<bean id="entity" class="entity.TestEntity">
		<!-- 使用<![CDATA[]]>标记处理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="entity.User">
				<property name="username">
					<value>Mr. Inner</value>
				</property>
			</bean>
		</property>
		<!-- 注入List类型 -->
		<property name="list">
			<list>
				<!-- 定义List中的元素 -->
				<value>足球</value>
				<value>篮球</value>
			</list>
		</property>
		<!-- 注入数组类型 -->
		<property name="array">
			<list>
				<!-- 定义数组中的元素 -->
				<value>足球</value>
				<value>篮球</value>
			</list>
		</property>
		<!-- 注入Set类型 -->
		<property name="set">
			<set>
				<!-- 定义Set或数组中的元素 -->
				<value>足球</value>
				<value>篮球</value>
			</set>
		</property>
		<!-- 注入Map类型 -->
		<property name="map">
			<map>
				<!-- 定义Map中的键值对 -->
				<entry>
					<key>
						<value>football</value>
					</key>
					<value>足球</value>
				</entry>
				<entry>
					<key>
						<value>basketball</value>
					</key>
					<value>篮球</value>
				</entry>
			</map>
		</property>
		<!-- 注入Properties类型 -->
		<property name="props">
			<props>
				<!-- 定义Properties中的键值对 -->
				<prop key="football">足球</prop>
				<prop key="basketball">篮球</prop>
			</props>
		</property>
		<!-- 注入空字符串值 -->
		<property name="emptyValue">
			<value></value>
		</property>
		<!-- 注入null值 -->
		<property name="nullValue">
			<null/>
		</property>
	</bean>
</beans>


异常抛出增强

特点

在目标方法抛出异常时织入增强处理 可拔插的异常处理方案

 public void throwex() throws Exception {

        throw new Exception("人造异常");
    }
    
public void afterThrowing(JoinPoint jp,Exception e){
        System.out.println("调用 " + jp.getTarget() + " 的 " + jp.getSignature().getName()
                + " 方法。方法入参:" + Arrays.toString(jp.getArgs())+e.getMessage());
        //log.info(""+jp.getTarget()+jp.getSignature()+ Arrays.toString(jp.getArgs()));
    }  
        
<aop:config>
        <aop:pointcut id="pointcut"  expression="execution(  public void *(..))"/>
        <aop:aspect ref="loggerUntil">
            <aop:before method="before" pointcut-ref="pointcut"/>
            <aop:after-returning method="afterReturning" pointcut-ref="pointcut" returning="result"/>
            <aop:after-throwing method="afterThrowing" pointcut-ref="pointcut" throwing="e"/>
        </aop:aspect>
    </aop:config>

最终增强

特点

无论方法是否抛出异常,都会在目标方法最后织入增强处理,即:该增强都会得到执行 类似于异常处理机制中finally块的作用,一般用于释放资源 可以为各功能模块提供统一的,可拔插的处理方案

用法与before类似

<aop:after>

环绕增强

目标方法前后都可织入增强处理 功能最强大的增强处理 可获取或修改目标方法的参数、返回值,可对它进行异常处理,甚至可以决定目标方法是否执行

<aop:around>
public void around(ProceedingJoinPoint jp){
        System.out.println("调用 " + jp.getTarget() + " 的 " + jp.getSignature().getName()
                + " 方法。方法入参:" + Arrays.toString(jp.getArgs()));
        try {
             Object result = jp.proceed();
            System.out.println("调用 " + jp.getTarget() + " 的 " + jp.getSignature().getName()
                    + " 方法。方法返回值:" + result);
        } catch (Throwable e) {
            System.out.println("调用 " + jp.getTarget() + " 的 " + jp.getSignature().getName()
                    + " 方法。方法入参:" + Arrays.toString(jp.getArgs())+e.getMessage());
            e.printStackTrace();
        }finally {
            System.out.println("最终");
        }
    }

注解实现IOC

解释

注解方式将Bean的定义信息和Bean实现类结合在一起,简化配置

@Component:实现Bean组件的定义 @Repository :用于标注DAO类 @Service :用于标注业务类 @Controller :用于标注控制器类

@Repository("userDao") 
public class UserDaoImpl implements UserDao {
	…
}
与在XML配置文件中编写
<bean id="userDao" 
class="dao.impl.UserDaoImpl" /> 
等效

使用注意事项

要在配置文件头部加相应信息,并且开启扫描

<?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:p="http://www.springframework.org/schema/p"
       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-3.2.xsd">
    <bean id="helloSpring" class="demo.HelloSpring">
        <property name="who">
            <value>Spring</value>
        </property>
    </bean>

    <context:component-scan base-package="service,dao" />




</beans>

@Autowired

使用@Autowired注解实现Bean的自动装配,默认按类型匹配,可以使用@Qualifier指定Bean的名称

@Service("userService")
public class UserServices implements IUserservice{

    @Autowired
    private UserDao dao;


    @Override
    public void addUser(User User) {
        dao.add(User);
    }
    public void throwex() throws Exception {

        throw new Exception("人造异常");
    }
    public UserServices(UserDao dao) {

    }

    public UserServices() {
    }
}

@Resource

注解实现组件装配,默认按名称匹配

@Service("userService") 
public class UserServiceImpl implements UserService { 
	@Resource(name = "userDao")
	private UserDao dao; 
	…… 
}

注解配置切面

@Aspect

@Pointcut

@Before

@AfterReturning

@AfterThrowing

@Around

@Component("loggerUntil")
@Aspect
public class LoggerUntil {
   private static Logger log = Logger.getLogger(LoggerUntil.class);

   @Pointcut("execution(* service.UserServices.*(..))")
   public void pointcut(){};

   @Before("pointcut()")
    public void before(JoinPoint jp){
        System.out.println("调用 " + jp.getTarget() + " 的 " + jp.getSignature().getName()
                + " 方法。方法入参:" + Arrays.toString(jp.getArgs()));
        //log.info(""+jp.getTarget()+jp.getSignature()+ Arrays.toString(jp.getArgs()));
    }
    @AfterReturning(pointcut = "pointcut()",returning = "result")
    public void afterReturning(JoinPoint jp,Object result){
        System.out.println("调用 " + jp.getTarget() + " 的 " + jp.getSignature().getName()
                + " 方法。方法返回值:" + result);
        //log.info(""+jp.getTarget()+jp.getSignature()+result);
    }
    @AfterThrowing(pointcut = "pointcut()",throwing = "e")
    public void afterThrowing(JoinPoint jp,Exception e){
        System.out.println("调用 " + jp.getTarget() + " 的 " + jp.getSignature().getName()
                + " 方法。方法入参:" + Arrays.toString(jp.getArgs())+e.getMessage());
        //log.info(""+jp.getTarget()+jp.getSignature()+ Arrays.toString(jp.getArgs()));
    }
    @Around("pointcut()")
    public void around(ProceedingJoinPoint jp){
        System.out.println("调用 " + jp.getTarget() + " 的 " + jp.getSignature().getName()
                + " 方法。方法入参:" + Arrays.toString(jp.getArgs()));
        try {
             Object result = jp.proceed();
            System.out.println("调用 " + jp.getTarget() + " 的 " + jp.getSignature().getName()
                    + " 方法。方法返回值:" + result);
        } catch (Throwable e) {
            System.out.println("调用 " + jp.getTarget() + " 的 " + jp.getSignature().getName()
                    + " 方法。方法入参:" + Arrays.toString(jp.getArgs())+e.getMessage());
            e.printStackTrace();
        }finally {
            System.out.println("最终");
        }
    }
}

<?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:p="http://www.springframework.org/schema/p"
       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-3.2.xsd">
    <bean id="helloSpring" class="demo.HelloSpring">
        <property name="who">
            <value>Spring</value>
        </property>
    </bean>

    <context:component-scan base-package="service,dao,aop" />

    <aop:aspectj-autoproxy />



</beans>